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节点我会在后面写到的,客户端的代码就不贴出来了,就是很简单的,定义消息的,在源码里在给大家吧~~
- erlang gen_tcp 聊天室(node节点)
- erlang gen_tcp 聊天室(holl节点)
- erlang gen_tcp 聊天室(chat节点)
- 【Erlang】基于gen_tcp的聊天室
- ERLANG 节点(node)
- erlang-gen_tcp手册(翻译)
- erlang节点间通信使用erlang send 和使用gen_tcp socket性能的对比(
- Erlang简单gen_tcp例子
- Erlang gen_tcp补充(1)
- Erlang gen_tcp补充(2)
- gen_tcp gen_udp send {error, einval} (erlang笔记)
- erlang gen_tcp 解析 http协议
- [Erlang]port(gen_tcp)如何并行?
- erlang 聊天室
- Erlang gen_tcp和gen_server结合应用
- Erlang gen_tcp相关问题汇编索引
- erlang node
- Erlang TCP编程:聊天室
- 暑假函数模板小练习
- 我是如何写作一本软件+哲学式的书籍的(下)
- VC6启用"运行时类型识别" (RTTI)
- mysql索引回顾
- Shaders In Opengl
- erlang gen_tcp 聊天室(node节点)
- 【转载】深入理解Android中ViewGroup
- 判断ResultSet结果集是否为空
- 基于MFC-MSComm控件的PC与单片机串口通信编程
- OpenCV 获取CvMat的数据(用double数组设置CvMat矩阵)
- 获取http传输过来的http数据流
- 小试创建存储过程
- 正则表达式
- 这个网址必须收藏,解决viewpager嵌套viewpager和其他view 冲突问题