Erlang动态接受传入的tcp连接

Erlang动态接受传入的tcp连接,tcp,erlang,gen-event,Tcp,Erlang,Gen Event,我试图解决的问题是:拥有一个在特定端口上侦听的Erlang TCP服务器(代码应该驻留在某种面向外部的接口/API中),每个传入连接都应该由gen_服务器处理(甚至gen_TCP:accept应该在gen_服务器中编码),但实际上我并不想一开始就产生一个预定义数量的进程来接受传入连接)。这有可能吗?gen\u tcp:accept的问题在于它会阻塞,因此如果在gen\u服务器中调用它,则会阻止服务器接收其他消息。您可以尝试通过传递超时来避免这种情况,但这最终会导致最好避免的轮询形式。相反,你可以

我试图解决的问题是:拥有一个在特定端口上侦听的Erlang TCP服务器(代码应该驻留在某种面向外部的接口/API中),每个传入连接都应该由
gen_服务器
处理(甚至
gen_TCP:accept
应该在
gen_服务器
中编码),但实际上我并不想一开始就产生一个预定义数量的进程来接受传入连接)。这有可能吗?

gen\u tcp:accept的问题在于它会阻塞,因此如果在
gen\u服务器中调用它,则会阻止服务器接收其他消息。您可以尝试通过传递超时来避免这种情况,但这最终会导致最好避免的轮询形式。相反,你可以尝试;它使用内部未记录的函数
prim\u inet:async\u accept
和其他
prim\u inet
函数来避免阻塞。

您应该使用Steve所说的“prim\u inet:async\u accept(侦听套接字,-1)”。 现在,传入的连接将被handle\u info回调接受 (假设您的接口也是gen_服务器),因为您使用了异步 接电话

在接受连接后,您可以生成另一个ger_服务器(我建议 gen_fsm),并通过调用 “gen_tcp:控制_进程(CliSocket,spwned进程的Pid)”

在此之后,该进程将接收来自套接字的所有数据 而不是通过您的接口代码。这是一个新的控制过程 将生成另一个连接。

基本过程 您应该有一个执行以下过程的静态进程(实现为
gen_server
或自定义进程):

  • 使用侦听传入连接
  • 每次它返回连接时,告诉主管生成一个工作进程(例如另一个
    gen_服务器
    进程)
  • 获取此进程的pid
  • 使用新返回的套接字和该pid调用
  • 将套接字发送到该进程
  • 注意:必须按照该顺序执行,否则新进程可能会在所有权移交之前使用套接字。如果不这样做,旧进程可能会在新进程已经接管时获取与套接字相关的消息,从而导致数据包丢失或处理错误

    监听过程应该只有一个职责,那就是为新的连接产生工作人员。调用
    gen_tcp:accept/1
    时,此进程将被阻止,这是正常的,因为已启动的工作进程将同时处理正在进行的连接。在accept上阻塞可确保启动新连接时的最快响应时间。如果流程需要在这段时间内执行其他操作,则可以与超时之间交错的其他操作一起使用

    缩放比例
    • 您可以在单个侦听套接字上使用
      gen_tcp:accept/1
      让多个进程等待,从而进一步提高并发性并最小化接受延迟

    • 另一个优化是预先启动一些套接字工作程序,以进一步减少接受新套接字后的延迟

    • 第三个也是最后一个,就是通过使用
      proc_lib
      ()在您自己的定制流程中实现OTP设计原则,使您的流程更加轻量级。然而,只有当您进行基准测试并得出结论认为是
      gen_服务器
      行为减慢了您的速度时,才应该这样做


    您可能希望签出并使用handle\u connection功能将您获得的进程转换为gen\u服务器

    但是如果我能找到一种方法将
    genu-tcp:accept
    中继到它自己的genu服务器中,我就不会在意它是否阻塞了。但我想事先不可能知道(比如从
    gen\u tcp:listen
    )您有一个必须接受的传入连接。感谢您指向gen\u nb\u服务器的指针
    !您在生产中使用过它吗?我认为您不需要
    gen\u nb\u server
    。您的案例非常简单。我从未在生产中使用过
    gen\u nb\u server
    ,但在生产中使用过
    prim\u inet:async\u accept
    。我推荐
    gen\u nb\u server
    ,因为最初的问题将
    gen\u server
    作为一项要求。我同意使用
    proc_lib
    过程会更好、更容易;这正是我们产生接受者的方式。只需从其他地方剪切并粘贴,而不需要属性。是的,我已经从我自己的erlang应用程序中剪切并粘贴了它。我需要获得自己的许可吗?抱歉,它看起来像是第一次查看邮件列表对话框中的某个片段。它是ok Peer.。您已在SO中回答了我对同一应用程序的查询。:)谢谢,我将尝试这种方法,因为它似乎是最可行的