【问题标题】:Erlang accept incoming tcp connections dynamicallyErlang 动态接受传入的 tcp 连接
【发布时间】:2011-07-23 16:37:49
【问题描述】:

我要解决的问题:拥有一个侦听特定端口的 Erlang TCP 服务器(代码应驻留在某种面向外部的接口/API 中),并且每个传入连接应由 gen_server 处理(即甚至gen_tcp:accept 也应该在gen_server 中编码),但我实际上并不想最初生成预定义数量的接受传入连接的进程)。这有可能吗?

【问题讨论】:

    标签: tcp erlang gen-event


    【解决方案1】:

    gen_tcp:accept 的问题在于它会阻塞,所以如果你在 gen_server 中调用它,就会阻止服务器接收其他消息。您可以尝试通过超时来避免这种情况,但这最终相当于一种最好避免的轮询形式。相反,您可以尝试Kevin Smith's gen_nb_server;它使用内部未记录的函数prim_inet:async_accept 和其他prim_inet 函数来避免阻塞。

    【讨论】:

    • 但如果我能找到一种方法将gen_tcp:accept 中继到它自己的 gen_server 中,我就不会在意它是否会阻塞。但我想不可能预先知道(比如从gen_tcp:listen)你有一个你必须接受的传入连接。感谢您指向gen_nb_server 的指针!你在生产中使用过吗?
    • 我认为您不需要 gen_nb_server 来完成您的工作。你的案子很简单。
    • 我从未在生产中使用过gen_nb_server,但在生产中使用过prim_inet:async_accept
    • 我推荐gen_nb_server,因为原始问题将gen_server 列为要求。我同意使用proc_lib 过程可能会更好、更容易;这正是我们在Yaws 中生成接受者的方式。
    【解决方案2】:

    您应该使用 Steve 所说的“prim_inet:async_accept(Listen_socket, -1)”。 现在传入的连接将被您的 handle_info 回调接受 (假设您的接口也是 gen_server)因为您使用了异步 接听电话。

    在接受连接后,您可以生成另一个 ger_server(我建议 gen_fsm) 并通过调用将其作为“控制过程” "gen_tcp:controlling_process(CliSocket, 生成进程的Pid)"。

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

    【讨论】:

    • 只是从其他地方剪切和粘贴而不注明出处。
    • 是的,我已经从我自己的 erlang 应用程序中剪切并粘贴了它。我需要获得自己的许可吗?
    • 抱歉,第一次查看时,它看起来像是邮件列表对话中的一些片段。
    • 没关系 Peer..you 已经回答了我对 SO 中同一个应用程序的查询。 :)
    【解决方案3】:

    基本流程

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

    1. 使用gen_tcp:accept/1 监听传入连接
    2. 每次它返回一个连接时,告诉主管派生一个工作进程(例如另一个 gen_server 进程)
    3. 获取此进程的 pid
    4. 使用新返回的套接字和该 pid 调用 gen_tcp:controlling_process/2
    5. 将套接字发送到该进程

    注意:必须按此顺序进行操作,否则新进程可能会在所有权移交之前使用套接字。如果不这样做,当新进程已经接管时,旧进程可能会收到与套接字相关的消息,从而导致丢弃或错误处理的数据包。

    监听进程应该只负责一项职责,那就是为新连接生成工作线程。这个进程在调用gen_tcp:accept/1 时会阻塞,这很好,因为启动的worker 将同时处理正在进行的连接。接受阻塞可确保启动新连接时的最快响应时间。如果进程需要在中间做其他事情,gen_tcp:accept/2 可以与其他在超时之间交错的操作一起使用。

    缩放

    • 您可以让多个进程在单个侦听套接字上使用 gen_tcp:accept/1 等待,从而进一步提高并发性并最大限度地减少接受延迟。

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

    • 第三个也是最后一个,通过使用 proc_lib (more info) 在您自己的自定义流程中实施 OTP 设计原则,使您的流程更加轻量级。但是,只有在您进行基准测试并得出结论是 gen_server 行为会减慢您的速度时,您才应该这样做。

    【讨论】:

    • 谢谢,我会尝试这种方法,因为它似乎最可行
    【解决方案4】:

    您可能想查看http://github.com/oscarh/gen_tcpd 并使用handle_connection 函数将您获得的进程转换为gen_server。

    【讨论】:

      猜你喜欢
      • 2015-04-14
      • 1970-01-01
      • 2010-11-17
      • 2012-10-10
      • 2012-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 2021-03-14
      相关资源
      最近更新 更多