`
coderplay
  • 浏览: 578113 次
  • 性别: Icon_minigender_1
  • 来自: 广州杭州
社区版块
存档分类
最新评论

tcp_server.erl注解

阅读更多
java 代码
 
  1. %% Copyright (C) 2002, Joe Armstrong  
  2. %% File    : tcp_server.erl  
  3. %% Author  : Joe Armstrong (joe@sics.se)  
  4. %% Purpose : Keeps track of a number of TCP sessions  
  5. %% Last modified: 2002-11-17  
  6.   
  7. -module(tcp_server).  
  8.   
  9. -export([start_raw_server/4, start_client/3,  
  10.      stop/1, children/1]).  
  11.   
  12. -define(KILL_DELAY, 1000).  
  13.   
  14. %% -export([start_child/3]).  
  15.   
  16. %% start_raw_server(Port, Fun, Max)  
  17. %%   This server accepts up to Max connections on Port  
  18. %%   The *first* time a connection is made to Port  
  19. %%   Then Fun(Socket) is called.   
  20. %%   Thereafter messages to the socket result in messsages to the handler.  
  21.   
  22. %% a typical server is usually written like this:  
  23.   
  24. %% To setup a lister  
  25.   
  26. %% start_server(Port) ->      
  27. %%     S = self(),  
  28. %%     process_flag(trap_exit, true),  
  29. %%     tcp_server:start_raw_server(Port,   
  30. %%              fun(Socket) -> input_handler(Socket, S) end,   
  31. %%              15,  
  32. %%                              0)  
  33. %%     loop().  
  34.   
  35. %% The loop() process is a central controller that all  
  36. %% processes can use to synchronize amongst themselfves if necessary  
  37. %% It ends up as the variable "Controller" in the input_handler  
  38.   
  39. %% A typical server is written like this:  
  40.   
  41. %% input_handler(Socket, Controller) ->  
  42. %%     receive  
  43. %%  {tcp, Socket, Bin} ->  
  44. %%      ...  
  45. %%      gen_tcp:send(Socket, ...)  
  46. %%   
  47. %%  {tcp_closed, Socket} ->  
  48. %%  
  49. %%   
  50. %%  Any ->  
  51. %%      ...  
  52. %%   
  53. %%     end.  
  54.   
  55. start_client(Host, Port, Length) ->  
  56.      gen_tcp:connect(Host, Port,  
  57.              [binary,   
  58.               {active, true},   
  59.               {packet, 2},  
  60.               {packet_size, Length}], 30000).  
  61.                        
  62. %% Note when start_raw_server returns, it should be ready to  
  63. %% Immediately accept connections  
  64. %% 作用  
  65. %%      当start_raw_server返回时, 就可以接受连接啦  
  66. %% 参数  
  67. %%      Port    服务器监听端口  
  68. %%      Fun     数据处理函数  
  69. %%      Max     最大连接数  
  70. %%      Length  最大包的长度
  71. start_raw_server(Port, Fun, Max, Length) ->  
  72.     Name = port_name(Port), % 用端口号来命名进程   
  73.     case whereis(Name) of  
  74.     undefined ->            % 如果端口还未定义的话,则启动  
  75.         Self = self(),  
  76.         Pid = spawn_link(fun() ->   % 产生一个新进程  
  77.                      cold_start(Self, Port, Fun, Max, Length)   % 冷启动  
  78.                  end),  
  79.         receive  
  80.         {Pid, ok} ->  
  81.             register(Name, Pid), % 接收到  
  82.             {ok, Pid};  
  83.         {Pid, Error} ->  
  84.             Error  
  85.         end;  
  86.     _Pid ->             % 如果端口已定义,则报错  
  87.         {error, already_started}  
  88.     end.  
  89.   
  90. stop(Port) when integer(Port) ->  
  91.     Name = port_name(Port),  
  92.     case whereis(Name) of  
  93.     undefined ->  
  94.         not_started;  
  95.     Pid ->  
  96.         exit(Pid, kill),  
  97.         (catch unregister(Name)),  
  98.         stopped  
  99.     end.  
  100.   
  101. children(Port) when integer(Port) ->  
  102.     port_name(Port) ! {children, self()},   %   
  103.     receive  
  104.     {session_server, Reply} -> Reply  
  105.     end.  
  106.   
  107. %% 作用  
  108. %%      以端口号做为服务名称  
  109. %% 参数  
  110. %%      端口号  
  111. port_name(Port) when integer(Port) ->  
  112.     list_to_atom("portServer" ++ integer_to_list(Port)).  
  113.   
  114. %% 作用  
  115. %%      启动服务  
  116. %%  参数  
  117. %%      Master      所有者  
  118. %%      Port        端口  
  119. %%      Fun         处理函数  
  120. %%      Max         数大连接数  
  121. %%      Length      最大包的长度
  122. cold_start(Master, Port, Fun, Max, Length) ->  
  123.     process_flag(trap_exit, true),  % 设置退出陷阱  
  124.     io:format("Starting a port server on ~p...~n",[Port]),  
  125.     % 绑定到端口,进行监听  
  126.     case gen_tcp:listen(Port, [binary,  
  127.                    %% {dontroute, true},  
  128.                    {nodelay,true},  
  129.                    {packet_size, Length},  
  130.                    {packet, 2},  
  131.                    {backlog, 1024},  
  132.                    {reuseaddr, true},   
  133.                    {active, false}]) of  
  134.     {ok, Listen} ->  
  135.         %% io:format("Listening on:~p~n",[Listen]),  
  136.         Master ! {self(), ok},  % 发送成功消息  
  137.         New = start_accept(Listen, Fun), % 开始接受连接   
  138.         %% Now we're ready to run  
  139.         socket_loop(Listen, New, [], Fun, Max); % 接受连接后,开始网络通信了   
  140.     Error ->  
  141.         Master ! {self(), Error}  
  142.     end.  
  143.   
  144. %% Don't mess with the following code uless you really know what you're   
  145. %% doing (and Thanks to Magnus for heping me get it right)  
  146. %% 作用  
  147. %%      接受连接后,开始运作  
  148. socket_loop(Listen, New, Active, Fun, Max) ->  
  149.     receive  
  150.     {istarted, New} ->  
  151.         Active1 = [New|Active], % 参见start_child,把新连接加入到活动列表中  
  152.         possibly_start_another(false, Listen, Active1, Fun, Max);  
  153.     {'EXIT', New, _Why} ->  
  154.         %%io:format("Child exit=~p~n",[Why]),  
  155.         possibly_start_another(false, Listen, Active, Fun, Max);  
  156.     {'EXIT', Pid, _Why} ->  
  157.         %%io:format("Child exit=~p~n",[Why]),  
  158.         Active1 = lists:delete(Pid, Active),  
  159.         possibly_start_another(New, Listen, Active1, Fun, Max);  
  160.     {children, From} ->  
  161.         From ! {session_server, Active},  
  162.         socket_loop(Listen, New, Active, Fun, Max);  
  163.     Other ->  
  164.         io:format("Here in loop:~p~n",[Other])  
  165.     end.  
  166.   
  167. possibly_start_another(New, Listen, Active, Fun, Max) when pid(New) ->  
  168.     socket_loop(Listen, New, Active, Fun, Mzax);  
  169. possibly_start_another(false, Listen, Active, Fun, Max) ->  
  170.     case length(Active) of  
  171.     N when N < Max ->  
  172.         New = start_accept(Listen, Fun),  
  173.         socket_loop(Listen, New, Active, Fun, Max);  
  174.     _ ->  
  175.         error_logger:warning_report(  
  176.           [{module, ?MODULE},  
  177.            {line, ?LINE},  
  178.            {message, "Connections maxed out"},  
  179.            {maximum, Max},  
  180.            {connected, length(Active)},  
  181.            {now, now()}]),  
  182.         socket_loop(Listen, false, Active, Fun, Max)  
  183.     end.  
  184.   
  185. %% 作用  
  186. %%      开始接受连接啦  
  187. %% 参数  
  188. %%      Listen  监听的Socket  
  189. %%      Fun     数据处理函数  
  190. start_accept(Listen, Fun) ->  
  191.     S = self(),  
  192.     spawn_link(fun() -> start_child(S, Listen, Fun) end). % 一个进程处理一个连接  
  193.   
  194. start_child(Parent, Listen, Fun) ->  
  195.     case gen_tcp:accept(Listen) of  % 接受一个连接  
  196.     {ok, Socket} ->  
  197.         Parent ! {istarted,self()}, % 参见socket_loop, tell the controller  
  198.         inet:setopts(Socket, [{nodelay,true},  
  199.                   {packet, 2},  
  200.                   {active, true}]), % before we activate socket  
  201.         Fun(Socket); % 这里应用了数据处理函数Fun  
  202.     _Other ->  
  203.         exit(oops)  
  204.     end.  
  205.   
  206.           
分享到:
评论

相关推荐

    ud.rar_user_default.erl

    标题中的"ud.rar_user_default.erl"表明这是一个与Erlang编程语言相关的压缩包,具体是一个名为"user_default.erl"的源代码文件。Erlang是一种面向并发、分布式和容错的编程语言,常用于构建高可用性系统,如电信、...

    ejabberd中mod_privacy_odbc.erl实现没有完全遵循xmpp协议

    标题中的“ejabberd中mod_privacy_odbc.erl实现没有完全遵循xmpp协议”指出,ejabberd服务器的模块mod_privacy_odbc在处理数据库操作时可能存在与XMPP(可扩展消息处理即时协议)标准不完全一致的问题。ejabberd是一...

    otp_src_21.2.tar.gz

    sudo cp -r rabbitmq_server-3.7.3 /usr/local/rabbitmq sudo ln -s /usr/local/rabbitmq/sbin/rabbitmq-server /usr/bin sudo rabbitmq-server ``` 在RabbitMQ安装完成后,你可以通过Web管理界面或命令行工具`...

    otp_src_18.3.7z

    erl -version ``` 6. **设置环境变量**:为了方便后续使用,可以将Erlang的bin目录添加到PATH环境变量中。编辑~/.bashrc或~/.bash_profile文件,添加以下行: ``` export PATH=$PATH:/usr/local/lib/erlang/bin...

    otp_src_22.0.tar.gz

    1. **源码文件**:Erlang 源代码文件(以 .erl 扩展名结尾),这些文件包含了 OTP 库、模块和函数实现。 2. **Makefiles**:编译指令文件,用于指导如何编译和链接源代码。 3. **文档**:可能包含 HTML 或 PDF 格式...

    最新版 erlang安装包 otp_src_21.3.tar.gz

    - 安装完成后,你可以通过运行`erl`命令来启动Erlang shell,如果一切顺利,你应该看到Erlang的欢迎界面。 - 使用`erl -version`可以查看Erlang的版本,确认是否为21.3。 8. **设置环境变量**: - 可能需要将...

    Erlang otp_win64_21.1.exe otp_win32_21.1.exe

    3. 安装后,需要将Erlang的bin目录添加到系统的PATH环境变量中,以便命令行可以找到erl等工具。 在安装完成后,可以继续安装RabbitMQ。RabbitMQ的安装通常涉及下载其二进制包,配置环境变量,启动服务,并根据应用...

    otp_src_23.1.tar.gz

    erl -version ``` Erlang OTP的源码安装允许用户自定义编译选项,比如添加特定的编译标志或链接库,以满足特定需求。同时,源码安装也方便了开发者对Erlang语言和 OTP 库的深入研究。 在实际开发中,Erlang OTP...

    erlang otp_src_20.2.tar.gz

    7. **启动和管理RabbitMQ**:安装完成后,可以使用`sudo rabbitmq-server start`启动RabbitMQ服务器,`sudo rabbitmq-plugins enable rabbitmq_management`启用管理插件以访问Web管理界面。管理界面默认在`...

    erl:otp_src_24.0.5.tar.gz

    标题中的"erl:otp_src_24.0.5.tar.gz"指的是Erlang的源码包,其中"otp_src_24.0.5"是Erlang/OTP (Open Telecom Platform) 的24.0.5版本的源代码。Erlang是一种面向并发的、函数式的编程语言,常用于构建高可用性和...

    test_udp.erl

    使用erlang进行UDP测试

    erl_default:一个不错的user_default.erl以及您在erlang项目中可能需要的其他东西

    错误默认该项目旨在包括大量用于调试,开发和测试erlang项目的帮助程序。user_default user_default是一个文件,可以在其中调用所有导出的函数而无需从外壳程序获取模块前缀的情况。 有关user_default的文档,请在...

    otp_src_22.0_h.tar.gz

    OTP提供了几个设计良好的应用框架,如gen_server、gen_event、gen_fsm等,它们是基于行为模式的模块,简化了并发编程和状态管理。 5. **分布式功能** OTP支持跨节点的分布式计算,使得在多台机器上构建分布式系统...

    erlang-25.0-1.el8.x86_64.rpm

    erlang 安装包。 rabbitmq 安装所需要的

    erlang_otp_src_22.3.tar.gz

    Erlang OTP (Open Telephony Platform) 是一种高级编程语言,专为构建高并发、分布式、容错性强的系统而设计。22.3 版本是 Erlang OTP 的一个稳定版本,它提供了许多增强的功能和性能改进。下面将详细介绍这个版本的...

    otp_src_22.1.tar.gz.zip

    5. 验证安装:安装完成后,可以使用 `erl` 命令来启动 Erlang shell,验证是否正确安装。 完成 Erlang 的安装后,可以继续安装 RabbitMQ。通常,这涉及下载 RabbitMQ 的二进制包或源代码,配置,然后启动服务。在 ...

    erl_to_html:使用解析转换和erl_id_trans.erl将erlang代码转换为跨度为_everything_HTML

    erl_to_html 使用解析变换和erl_id_trans.erl Erlang的代码转换为HTML,跨度的一切。...我不知道我需要怎么做许可证,但是由于我是从Erlang示例代码中复制erl_id_trans.erl,因此我正在使用Erlang公共许可证。

    otp_src_21.1.tar.gz

    1. **模块化设计**:OTP提供了各种预定义的进程行为模式(gen_server、gen_event、gen_fsm等),便于开发者创建符合特定模式的进程,提高了代码复用和可维护性。 2. **分布式计算**:Erlang OTP支持跨节点的进程...

    erlang-erl_interface-19.3.6.4-1.el7.x86_64.rpm

    erlang-erl_interface-19.3.6.4-1.el7.x86_64.rpm

Global site tag (gtag.js) - Google Analytics