学了Erlang三个礼拜,做了这个程序,费了4天时间,这四天查阅了wxwidgts,wxErlang,等界面设计的资料,英文还是不行 呀!今天被老大说我的程序使用的协议不规范。我想这算个RC版吧,哈哈。本程序使用Erlang + wxErlang + mysql。Erlang这东西不火,也是个麻烦,Web上Erlang的资料可怜地少,先贴个效果图吧。
这个程序:不小心搞了个变量去匹配消息,然后变量不变这个害我好惨。记住:Erlang变量特性,变量不变
程序很拙劣,但我还是想贴出来,以示我Erlang入门了,哈哈。
客户端:client.erl 服务端:server.erl
程序:在线多人聊天系统
服务器端代码:
-module(server).
-export([start/0]).
% 启动一个服务器
start() ->
case gen_tcp:listen(1110,[binary,{packet,0},{reuseaddr,true},{active,true}]) of
{ok,Listen} ->
spawn(fun() -> par_connect(Listen) end);
{error,Why} ->
io:format(“server start error,the reason maybe ~p~n
now is going restart~n“,[Why]),
end.
% 建立链接
start()
par_connect(Listen) ->
case gen_tcp:accept(Listen) of
{ok,Socket} ->
spawn(fun() -> par_connect(Listen) end),
loop(Socket);
{error,Why} ->
io:format(“create internet connect failed,the reasom maybe ~p~n
now is going reconnect~n“,[Why]),
par_connect(Listen)
end.
% 监听消息
loop(Socket) ->
receive
{tcp,Socket,Bin} ->
case binary_to_term(Bin) of
{login,Username,Password} -> % 请求登入聊天系统
handleLoginRequest(Username,Password,Socket),
loop(Socket);
{socket,ChatRoom} -> % 用户选择了聊天房间
handleChoseRoom(ChatRoom,Socket),
loop(Socket);
{msg,ChatRoom,Username,Msg} -> % 用户发送聊天信息
handleChatMsg(ChatRoom,Username,Msg),
loop(Socket);
{totalusers,ChatRoom} -> % 用户请求在线总人数
handleTotalUsersRequest(ChatRoom,Socket),
loop(Socket);
{logintimes,Username} -> % 用户请求登入系统次数
handleLoginTimesRequest(Username,Socket),
loop(Socket);
{chattimes,Username} -> % 用户请求聊天次数
handleChatTimesRequest(Username,Socket),
loop(Socket);
{lastlogin,Username} -> % 用户请求最近一次登陆系统时间
handleLastLoginRequest(Username,Socket),
loop(Socket)
end;
{tcp_closed,Socket} -> % 用户登出聊天系统
handleTcpClosed(Socket),
loop(Socket)
end.
% 请求登入聊天系统
handleLoginRequest(Username,Password,Socket) ->
mysql:start_link(chat,“localhost”,“root”,“weihua0620″,“test”), % 链接数据库
case checkAccount(Username,Password) of % 检测用户名,密码是否合法
ok -> RoomList = getChatRoomList(); % 合法,获取聊天房间
nok -> RoomList = [] % 不合法,返回空聊天房间
end,
% 向客户端发送聊天房间列表
gen_tcp:send(Socket,term_to_binary({roomlist,RoomList})),
% 登入成功 更新登入次数 和 最后一次登陆时间
case RoomList of
[] -> loginfailed;
_ ->
Sql1 = lists:concat(["select login_times from account
where username = '",Username,"'"]),
case mysql:fetch(chat,Sql1) of % 提取登入次数
{data,Result} ->
[[Logintimes]] = mysql:get_result_rows(Result),
Sql2 = lists:concat(["update account set login_times = ",
Logintimes+1," where username = '",Username,"'"]), mysql:fetch(chat,Sql2); % 更新登入次数
{error,_Result} -> no
end,
Sql3 = lists:concat(["update account set last_login = now()
where username = '",Username,"'"]), mysql:fetch(chat,Sql3) % 更新最近一次登入时间
end.
% 检查用户名,密码是否正确
checkAccount(Username,Password) ->
Sql = lists:concat(["select * from account where username = '",
Username,"'and password = '",Password,"'"]),
case mysql:fetch(chat,Sql) of
{data,Result} ->
case mysql:get_result_rows(Result) of
[] -> nok; % 用户名,密码有误
_ -> ok % 用户名,密码有效
end;
{error,_Result} ->
checkAccount(Username,Password)
end.
% 获取聊天房间列表
getChatRoomList() ->
Sql = “select roomname from chatroom” ,
case mysql:fetch(chat,Sql) of
{data,Result} ->
case mysql:get_result_rows(Result) of
[] -> [];
RoomList -> binaryToList(RoomList) % 处理提取出来的二进制数据
end;
{error,_Result} ->
getChatRoomList()
end.
binaryToList([]) -> [];
binaryToList([[H]|T]) ->
[binary_to_list(H)|binaryToList(T)].
% 用户选择了聊天房间,保存当前 Socket handleChoseRoom(ChatRoom,Socket) ->
Soc = binary_to_list(base64:encode(term_to_binary(Socket))),
Sql = lists:concat(["insert into roomsocket values('",ChatRoom,"','",Soc,"')"]),
mysql:fetch(chat,Sql).
% 用户发送聊天信息
handleChatMsg(ChatRoom,Username,Msg) ->
% 更新用户聊天次数,每发一条聊天 msg ,聊天次数 +1
Sql = lists:concat(
["select chat_times from account where username = '",Username,"'"] ),
case mysql:fetch(chat,Sql) of
{data,Result} ->
[[Chattimes]] = mysql:get_result_rows(Result),
Sql2 = lists:concat(["update account set chat_times = ",Chattimes+1,
" where username = '",Username,"'"]),
mysql:fetch(chat,Sql2);
{error,_Result} -> no
end,
% 在聊天房间广播用户Username 的 Msg
sendRoomMsg(ChatRoom,Username,Msg).
% 向聊天房间广播用户 Username 的消息 Msg sendRoomMsg(ChatRoom,Username,Msg) ->
Sql = lists:concat(
["select socket from roomsocket where roomname = '",ChatRoom,"'"] ),
case mysql:fetch(chat,Sql) of
{data,Result} ->
case mysql:get_result_rows(Result) of
[] -> nosocket;
SocketList ->
Sockets = binaryToList(SocketList), % 处理提取出来的二进制数据
sendMessage(Username,Sockets,Msg)
end;
{error,_Result} ->
sendRoomMsg(ChatRoom,Username,Msg)
end.
% 向房间内的所有用户(socket识别)广播消息 sendMessage(_Username,[],_Msg) ->[]; sendMessage(Username,Sockets,Msg) ->
[H|T] = Sockets,
Socket = binary_to_term(base64:decode(H)),
gen_tcp:send(Socket,term_to_binary({msg,Username,Msg})),
sendMessage(Username,T,Msg).
% 用户请求在线总人数
handleTotalUsersRequest(ChatRoom,Socket) ->
Sql = lists:concat(
["select count(socket) from roomsocket where roomname = '",ChatRoom,"'"]),
case mysql:fetch(chat,Sql) of
{data,Result} ->
[[Num]] = mysql:get_result_rows(Result),
gen_tcp:send(Socket,term_to_binary({totalusers,Num}));
{error,_Result} -> no
end.
% 用户请求登入系统次数
handleLoginTimesRequest(Username,Socket) ->
Sql = lists:concat(
["select login_times from account where username = '",Username,"'"]),
case mysql:fetch(chat,Sql) of
{data,Result} ->
[[LoginTimes]] = mysql:get_result_rows(Result),
gen_tcp:send(Socket,term_to_binary({logintimes,LoginTimes}));
{error,_Result} -> no
end.
% 用户请求聊天次数
handleChatTimesRequest(Username,Socket) ->
Sql = lists:concat(
["select chat_times from account where username = '",Username,"'"]),
case mysql:fetch(chat,Sql) of
{data,Result} ->
[[ChatTimes]] = mysql:get_result_rows(Result),
gen_tcp:send(Socket,term_to_binary({chattimes,ChatTimes}));
{error,_Result} ->no
end.
% 用户请求最近一次登陆系统时间
handleLastLoginRequest(Username,Socket) ->
Sql = lists:concat(
["select last_login from account where username = '",Username,"'"]),
case mysql:fetch(chat,Sql) of
{data,Result} ->
[[{ datetime,
{{Year,Month,Day},
{Hour,Minute,Second}} }]] =mysql:get_result_rows(Result), LastLoginTime = lists:concat(
[Year,":",Month,":",Day," ",Hour,":",Minute,":",Second] ), gen_tcp:send(Socket,term_to_binary({lastlogin,LastLoginTime}));
{error,_Result} ->no
end.
% 用户退出了聊天系统,删除用户的在数据库中的 socket记录
handleTcpClosed(Socket) ->
Soc = binary_to_list(base64:encode(term_to_binary(Socket))),
Sql = lists:concat(["delete from roomsocket where socket = '",Soc,"'"]),
mysql:fetch(chat,Sql).
客户端代码:
-module(client).
-include_lib(“wx/include/wx.hrl”).
-export([start/0]). | ||
-define(ABOUT,8110). |
% |
关于系统 |
-define(ONLINEUSERNUM,8111). |
% |
在线用户数(同一个聊天房间) |
-define(LOGINTIMES,8112). |
% |
用户登入次数 |
-define(CHATTIMES,8113). |
% |
用户聊天次数(没法送一条 msg,聊天次数 +1) |
-define(MYACCOUNT,8114). |
% |
用户最后一次登入时间 |
-define(EXIT,8115). |
% |
退出系统 |
-define(SENDMSG,8116). |
% |
发送消息 |
start() ->
Username = checkLoginInputInfo(usernameDialog()), % 获取登入用户名
Password = checkLoginInputInfo(passwordDialog()), % 获取用户密码
Socket = connect(), % 建立Tcp链接,获取Socket
ChatRoomList = loginServer(Username,Password,Socket), % 登入服务器,获取聊天房间列表
ChatRoom = checkLoginInputInfo(choseChatRoom(ChatRoomList)), % 获取用户选择的聊天房间
loginChatRoom(Username,ChatRoom,Socket). % 登入聊天房间
% 获取登入用户名
usernameDialog()
请发表评论