erlang gen_tcp 聊天室(node节点)

来源:互联网 发布:阿里钱盾软件 编辑:程序博客网 时间:2024/05/22 05:18

自己写的一个简单的基于gen_tcp行为的聊天室:

因为技术要求,要服务器端要实现3个节点,分别是(node,holl,chat节点)。

客户端要实现的是 和服务端的通信,注册,登陆和聊天的功能


(1)

opt_node模块:用于监听port端口(自己定义的),并且用于监听多个客户端发来的请求。

-module(opt_node).%% ====================================================================%% API functions%% ====================================================================-behaviour(gen_server). -export([]).%% gen_server callbacks  -export([init/1, handle_call/3, handle_cast/2, handle_info/2,       terminate/2, code_change/3]).  -compile(export_all).-define(Server_Node,node).-define(Node_Holl,holl@simsunny).-define(Server_Holl,holl).-define(Node_Chat,chat@simsunny).-define(Server_Chat,chat).%% ====================================================================%% Internal functions%% ====================================================================s() -> gen_server:start_link({local,?Server_Node}, ?MODULE, [], []).  stop()  -> gen_server:call(?Server_Node, stop).  init([])->io:format("-----------------supervison------------------------\n"),server(),{ok,[]}.handle_call(stop, _From, Tab) ->      {stop, normal, stopped, Tab}.    handle_cast(_Msg, State) -> {noreply, State}. handle_info(_Info, State) -> {noreply, State}.  terminate(_Reason, _State) -> ok.  code_change(_OldVsn, State,_Extra) -> {ok, State}.server()->io:format("----------------server------------------------\n"),case gen_tcp:listen(2345,[binary,{packet,4},  {reuseaddr,true},{active,true}] ) of{ok,Listen}->spawn(fun()->connect(Listen,0)end);{error,Reason}->io:format(" listen is wrong:~p~n",[Reason])end.connect(Listen,Num)->case gen_tcp:accept(Listen) of{ok,Socket}->io:format("--------------------accpet()----------------------\n"),io:format("Socket is:~p~n", [Socket]),Server_name=list_to_atom("opt_node_server"++integer_to_list(Num)),%% Server_name_super=list_to_atom("super_node_server"++integer_to_list(Num)),New_num=Num+1,{ok,Pid}=opt_node_connect:s(Server_name),gen_tcp:controlling_process(Socket, Pid),connect(Listen,New_num);{error,Why}->io:format("par_con error:~p~n",[Why])end.
函数解释:

gen_tcp:listen(2345,[binary,{packet,4},{reuseaddr,true},{active,true}] ) 表示监听2345的端口,

spawn(fun()->connect(Listen,0)end) 这里用spawn是应为调用 gen_tcp:listen函数,进程一直在等待连接,开一个新的进程用于处理请求

gen_tcp:controlling_process(Socket, Pid),表示将Socket交给Pid的进程来处理

(2)

opt_node_connect 模块:当客户端发来请求,就新建一个进程,该进程与客户端进行通信

-module(opt_node_connect).%% ====================================================================%% API functions%% ====================================================================-behaviour(gen_server). -export([init/1, handle_call/3, handle_cast/2, handle_info/2,       terminate/2, code_change/3]).  -compile(export_all).-define(Node_Holl,holl@simsunny).-define(Server_Holl,holl).-define(Node_Chat,chat@simsunny).-define(Server_Chat,chat).%% ====================================================================%% Internal functions%% ====================================================================s(Server_name) ->      gen_server:start_link({local,Server_name},?MODULE, [Server_name], []).  init([Server_name])->{ok,Server_name}.%% ====================================================================%%handle_call%% ==================================================================== %%quitehandle_call(stop, _From,Server_name) ->      {stop, normal, stopped, Server_name}.  %% ====================================================================%%handle_cast%% ==================================================================== %%registerhandle_cast({reigister,user_is_already,{socket,Socket}},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("register is error (user is already)\n"),gen_tcp:send(Socket,term_to_binary({register,n,user_is_already})),{noreply, Tab}; handle_cast({reigister,register_success,{{user,Name},{psw,Psw},{socket,Socket}}},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("register is ok \n"),gen_tcp:send(Socket,term_to_binary({register,y,{{user,Name},{psw,Psw}}})),{noreply, Tab}; %%loginhandle_cast({login,no_urers,{socket,Socket}},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("log is error (no users)\n"),gen_tcp:send(Socket,term_to_binary({login,n,no_urers})),{noreply, Tab}; handle_cast({login,psw_wrong,{socket,Socket}},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("log is error (psw wrong)\n"),gen_tcp:send(Socket,term_to_binary({login,n,psw_wrong})),{noreply, Tab}; handle_cast({login,success,{{user,Name},{psw,Psw},{socket,Socket}}},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("log is ok\n"),gen_tcp:send(Socket,term_to_binary({login,y,{{user,Name},{psw,Psw}}})),%% ets:insert(?Ets_Tab_Users, {Name,Socket}),{noreply, Tab};  %%get onlinehandle_cast({get_all_users,List_name,{socket,Socket}},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("get_all_users\n"),gen_tcp:send(Socket,term_to_binary({get_all_users,List_name})),{noreply, Tab};%%chat in roomhandle_cast({chat,{name,Name},{content,Msg},List},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("chat\n"),send(Name, List, Msg),{noreply, Tab};%%chat in grouphandle_cast({chat_gr,{name,Name},{content,Content},List_node},Tab)->io:format("------------------receive node-------------------------------\n"),io:format("chat_gr\n"),send(Name, List_node, Content),{noreply, Tab};handle_cast({no}, State) -> {noreply, State}. %% ====================================================================%%handle_info%% ==================================================================== handle_info({tcp, Socket, Bin}, Server_name)->  Msg=binary_to_term(Bin),io:format("------------------receive client-------------------------------\n"),io:format("msg:~p~n", [Msg]),case Msg of {register,{user,Name},{psw,Psw}}->Request={register,{user,Name},{psw,Psw},{socket,Socket},{server_Name,Server_name}},gen_server:call({?Server_Holl,?Node_Holl}, Request);{login,{user,Name},{psw,Psw}}->Request={login,{user,Name},{psw,Psw},{socket,Socket},{server_Name,Server_name}},gen_server:call({?Server_Holl,?Node_Holl}, Request);{get_all_users,{name,_Name}}->Request={get_all_users,{socket,Socket},{server_Name,Server_name}},gen_server:call({?Server_Chat,?Node_Chat}, Request);{chat,{name,Name},{content,Content}}->Request={chat,{name,Name},{content,Content},{server_Name,Server_name}},gen_server:call({?Server_Chat,?Node_Chat}, Request);{chat_group,{name,Name},{list,List},{msg,Content}}->Request={chat_group,{name,Name},{list,List},{msg,Content},{server_Name,Server_name}},gen_server:call({?Server_Chat,?Node_Chat}, Request);_->io:format("not reg \n")end,    {noreply, Server_name};  handle_info({tcp_closed,Socket}, Server_name) ->  io:format("client: is quite~p~n",[Socket]),Requset={quite,{socket,Socket},{server_name,Server_name}},gen_server:call({?Server_Chat,?Node_Chat},Requset),    {noreply,Server_name}. terminate(_Reason, _State) -> ok.  code_change(_OldVsn, State,_Extra) -> {ok, State}.send(Name,[{To_Name,Socket}|T],Msg)->Msg_info={{name,Name},{msg,Msg}},io:format("--------------------------------------------\n"),%% io:format("Name:~p~n",[Name]),%% io:format("TO_Name:~p~n",[To_Name]),case gen_tcp:send(Socket,term_to_binary(Msg_info)) ofok ->io:format(" send ok-------~n form:~p~n to:~p~n msg:~p~n socket:~p~n ",   [Name,To_Name,Msg,Socket]);_ ->io:format(" send error-------~n form:~p~n to:~p~n msg:~p~n socket:~p~n ",   [Name,To_Name,Msg,Socket])end,io:format("--------------------------------------------\n"),send(Name,T,Msg);send(_Name,[],_Msg)->over.

解释:该模块使用的是gen_server的行为模式,该模式中的handle_info用来接收系统发来的消息(具体的不太理解,哪些是系统的消息)。可以用来接收从客户端发来的消息,相当于receive .......end 的作用。

欢迎转载,请注明出处

holl节点和chat节点我会在后面写到的,客户端的代码就不贴出来了,就是很简单的,定义消息的,在源码里在给大家吧~~

原创粉丝点击