如何在gen_tcp上调用(和睡眠):同时接受并仍处理系统消息?

时间:2012-05-17 15:30:49

标签: erlang otp

我仍然对erlang / otp世界有点新意,所以我想这是一个非常基本的问题。不过我想知道做以下事情的正确方法是什么。

目前,我有一位顶级主管的申请。后者将监督调用gen_tcp:accept(在其上休眠)然后为每个接受的连接生成进程的工作者。注意:对于这个问题,listen()完成的地方无关紧要。

我的问题是关于使这些工作者(那些睡在gen_tcp:accept上的工作人员)遵循otp设计原则的正确方法,以便他们可以处理系统消息(处理关闭,跟踪等),根据我在这里读到的内容:http://www.erlang.org/doc/design_principles/spec_proc.html

所以,

  • 是否可以使用gen_fsm或gen_server等可用行为之一?我的猜测是否定的,因为对gen_tcp的阻塞调用:accept / 1。是否仍然可以通过指定接受超时来完成它?如果是这样,我应该在哪里拨打accept()?
  • 或者我应该从头开始编码(即:不使用现有的行为),如上面链接中的示例?在这种情况下,我想到了一个调用gen_tcp的主循环:accept / 2而不是gen_tcp:accept / 1(即:指定超时),然后立即编写接收块代码,这样我就可以处理系统消息了。这是正确/可接受的吗?

提前致谢:)

3 个答案:

答案 0 :(得分:1)

由于Erlang是事件驱动的,处理阻塞为accept / {1,2}的代码是很尴尬的。

就个人而言,我会有一个主管,其中有一个gen_server为听众,另一个主管为接受工人。 将接受工作人员设置为超时(gen_tcp:accept/2),有效地轮询,(尴尬的部分)而不是接收状态消息。

这样,如果一个工人死了,它就会被上面的主管重新启动。 如果侦听器终止,则重新启动,但不会在重新启动依赖于该侦听器的工作树和主管之前重新启动。 当然,如果顶级主管死亡,它会重新启动。 但是,如果您在树上supervisor:terminate_child/2,那么您可以有效地禁用该套接字的侦听器和所有接受器。稍后,supervisor:restart_child/2可以重新启动整个侦听器+接受器工作池。

如果您希望应用为您管理此问题,cowboy会实现上述目标。虽然面向http,但它很容易支持自定义处理程序,无论使用何种协议。

答案 1 :(得分:0)

您可以将其设为与此类似的gen_server:https://github.com/alinpopa/qerl/blob/master/src/qerl_conn_listener.erl

正如您所看到的,此过程正在执行tcp接受和处理其他消息(例如,停止(Pid) - > gen_server:cast(Pid,{close})。)

HTH, 阿林

答案 2 :(得分:0)

我实际上在另一个问题中找到了答案:Non-blocking TCP server using OTP principleshttp://20bits.com/article/erlang-a-generalized-tcp-server

编辑:对我有帮助的具体答案是:https://stackoverflow.com/a/6513913/727142