erlang tcp服务器和客户端的简单实现
来源:互联网 发布:js实现div隐藏显示 编辑:程序博客网 时间:2024/05/16 01:24
看了《erlang程序设计》的lib_chan代码,自己也试着写了一个,不过大部分代码都摘自lib_chan,做了一个改编。
-module(lib_comm).-export([start_server/1, stop_server/1, start_client/2, send/2]).stop_server(Port) when is_integer(Port) -> ServerName = list_to_atom("portServer" ++ integer_to_list(Port)), case whereis(ServerName) ofundefined -> not_started;Pid -> exit(Pid, kill), (catch unregister(ServerName)), stopped end.start_server(Port) ->io:format("start_server(), Pid: ~p~n", [self()]),spawn(fun() -> start_port_server(Port) end).start_port_server(Port) ->io:format("start_port_server(), Pid: ~p~n", [self()]),start_raw_server(Port, fun(Socket) -> start_port_instance(Socket) end, 100, 4).start_raw_server(Port, Fun, Max, PacketLength) ->io:format("start_raw_server(), Pid: ~p~n", [self()]),ServerName = list_to_atom("portServer" ++ integer_to_list(Port)),case whereis(ServerName) ofundefined ->Self = self(),Pid = spawn_link(fun() -> cold_start(Self,Port,Fun,Max,PacketLength) end),receive{Pid, ok} ->register(ServerName, Pid),{ok, self()};{Pid, Error} ->Errorend;_Pid -> {error, already_started} end.cold_start(Master,Port,Fun,Max,PacketLength) ->io:format("cold_start(), Pid: ~p~n", [self()]),process_flag(trap_exit, true),io:format("Starting a port server on ~p...~n",[Port]),case gen_tcp:listen(Port, [binary, {nodelay,true}, {packet, PacketLength}, {reuseaddr, true}, {active, true}]) of{ok, Listen} ->io:format("Listening to:~p~n",[Listen]),Master ! {self(), ok},_New = start_accept(Listen, Fun),io:format("New 1 : ~p~n", [_New]), socket_loop(Listen, Master, [], Fun, Max);Error ->Master ! {self(), Error}end.start_accept(Listen, Fun) -> S = self(), spawn_link(fun() -> start_child(S, Listen, Fun) end).start_child(Parent, Listen, Fun) ->io:format("Pid: ~p gen_tcp:accept ~n", [self()]),case gen_tcp:accept(Listen) of{ok, Socket} ->io:format("Pid: ~p accepted ~n", [self()]),Parent ! {istarted, self()}, % tell the controllerinet:setopts(Socket, [ {packet,4}, binary, {nodelay,true}, {active, true}]), io:format("running the child:~p Fun=~p~n", [Socket, Fun]),process_flag(trap_exit, true),case (catch Fun(Socket)) of{'EXIT', normal} -> true;{'EXIT', Why} -> io:format("Port process dies with exit:~p~n",[Why]), true;_ -> true %% not an exit so everything's ok endend.socket_loop(Listen, Master, Active, Fun, Max) ->receive{istarted, Pid} ->io:format("Pid = ~p istarted ~n", [Pid]), Active1 = [Pid|Active], possibly_start_another(Master, Listen,Active1,Fun,Max); {'EXIT', Master, _Why} -> io:format("Pid = ~p master exit, reason: ~p ~n", [Master, _Why]), socket_loop(Listen, Master, Active, Fun, Max); {'EXIT', Pid, _Why} -> io:format("Pid = ~p exit, reason: ~p ~n", [Pid, _Why]), Active1 = lists:delete(Pid, Active), possibly_start_another(Master, Listen,Active1,Fun,Max); _Other -> io:format("socket_loop() _Other = ~p~n", [_Other]), socket_loop(Listen, Master, Active, Fun, Max)end.possibly_start_another(Master, Listen, Active, Fun, Max) -> case length(Active) ofN when N < Max -> _New = start_accept(Listen, Fun), io:format("New 2: ~p~n", [_New]), socket_loop(Master, Listen, Active, Fun,Max);_ -> socket_loop(Master, Listen, Active, Fun, Max) end.start_port_instance(Socket) ->process_flag(trap_exit, true),MessageHandler = spawn_link(fun() -> start_server_biz() end),message_loop(Socket, MessageHandler).start_server_biz() ->server_biz_loop().server_biz_loop() ->receive{recv, Pid, Term} ->io:format("server recv message ~p~n", [Term]),Pid ! {send, Term},server_biz_loop();{closed, Pid} ->Pid ! closeend.message_loop(Socket, Pid) ->receive{tcp, Socket, Bin} -> Term = binary_to_term(Bin), Pid ! {recv, self(), Term}, message_loop(Socket, Pid);{tcp_closed, Socket} -> Pid ! {closed, self()};{'EXIT', Pid, _Why} -> gen_tcp:close(Socket);close -> gen_tcp:close(Socket);{send, Term} -> gen_tcp:send(Socket, term_to_binary(Term)), message_loop(Socket, Pid);UUg -> io:format("protocol error:~p~n",[UUg]), message_loop(Socket, Pid) end.start_client(Host, Port) ->Self = self(),spawn(fun() -> start_raw_client(Self, Host, Port) end),receive{ok, Pid} ->Pid;Error ->io:format("client connect failure, ~p~n", [Error]),Errorend.start_raw_client(Master, Host, Port) ->PacketLength = 4,Self = self(),Pid = spawn(fun() -> connect(Self, Host, Port, PacketLength) end),client_biz_loop(Master, Pid).connect(Parent, Host, Port, PacketLength) ->case gen_tcp:connect(Host, Port, [binary, {active, true}, {packet, PacketLength}]) of{ok, Socket} -> Parent ! {ok, self()}, message_loop(Socket, Parent);Error -> Parent ! {self(), Error}end.client_biz_loop(Master, Pid) ->receive{ok, Pid} ->Pid ! {send, "hello world"},Master ! {ok, Pid},client_biz_loop(Master, Pid);{recv, Pid, Term} ->io:format("client recv message: ~p~n", [Term]),client_biz_loop(Master, Pid);Error ->Master ! Error,Errorend.send(Pid, Term) -> Pid ! {send, Term}.按照下面方式调用:
lib_comm:start_server(8080).
Pid = lib_comm:start_client("localhost", 8080).
lib_comm:send(Pid, "aaaaa").
0 0
- erlang tcp服务器和客户端的简单实现
- python3实现TCP协议的简单服务器和客户端
- python3实现TCP协议的简单服务器和客户端
- TCP服务器、客户端的简单实现
- 简单的TCP服务器和客户端
- TCP实现客户端和服务器的通信
- Linux下的C语言编程——简单实现tcp客户端和服务器
- golang简单实现一个基于TLS/SSL的 TCP服务器和客户端
- python socket实现简单的(TCP/UDP)服务器/客户端
- 基于TCP的服务器和客户端的简单收发Demo
- 简单的TCP 流式socket 服务器和客户端代码示例
- TCP SOCKET服务器|客户端简单实现
- 基于erlang的简单Web服务器实现
- java 通过 socket 实现 服务器和客户端的通信 TCP
- 基于TCP协议实现服务器和客户端的通信程序
- 简单的TCP服务器与客户端
- 简单的TCP服务器与客户端通讯
- Tcp实现客户端和服务器端的简单互访
- DSP6000的几个简单优化技巧
- 数字信号处理的学习资源
- 排序算法的时间复杂度与稳定性
- size_t为何这么重要?
- 关于SVN的使用
- erlang tcp服务器和客户端的简单实现
- Java基础---hashmap的实现原理
- test
- Cocos2d-x动画,翻开,翻页,淡入淡出动画
- Could not get JDBC Connection
- 浅拷贝和深拷贝的区别
- Mashup
- Web应用过滤器Fileter
- 用JFinal框架自带的main方法运行正常的情况下,用tomcat发布项目出现css样式表引用错误和资源找不到问题。