gpt4 book ai didi

sockets - 与gen_tcp并行建立大量连接时出现CLOSED错误(错误?)

转载 作者:行者123 更新时间:2023-12-03 11:58:04 25 4
gpt4 key购买 nike

当尝试并行建立大量的TCP连接时,我观察到一些奇怪的行为,我认为gen_tcp中存在潜在的错误。

该方案是服务器在具有多个并发接受器的端口上监听。从客户端,我通过调用gen_tcp:connect/3建立连接,然后向服务器发送“Ping”消息,并在被动模式下等待“Pong”响应。依次执行“get_tcp:connect/3”调用时,所有工作都可以正常进行,包括大量连接(我测试到〜28000)。

尝试并行建立许多连接时会发生问题(取决于约75到几百之间的计算机)。虽然大多数连接仍然可以建立,但是某些连接失败,并在closed中出现gen_tcp:recv/3错误。奇怪的是,这些连接之前没有失败,对gen_tcp:connect/3gen_tcp:send/2的调用均成功
(即返回的ok)。在服务器端,我看不到这些“怪异”连接的匹配连接,即没有返回gen_tcp:accept/1。据我了解,成功的“get_tcp:connect/3”应在服务器端导致匹配的接受连接。

我已经提交了bug report,在那里您可以找到更详细的描述和最小的代码示例来演示该问题。我能够在Linux和Mac OS X以及不同的Erlang版本上重现该问题。

我的问题是:

  • 是否有人能够重现该问题并可以确认这是错误的行为?
  • 有任何解决方法的想法吗?如何解决此问题,而其他顺序地启动所有连接(这将永远)?
  • 最佳答案

    TCP 3向握手
    客户端服务器

      connect()│──┐          │listen()
    │ └──┐ │
    │ SYN │
    │ └──┐ │
    │ └▶│ STATE
    │ ┌──│SYN-RECEIVED
    │ ┌──┘ │
    │ SYN-ACK │
    │ ┌──┘ │
    STATE │◀┘ │
    ESTABLISHED│──┐ │
    │ └──┐ │
    │ └ACK │
    │ └──┐ │ STATE
    │ └▶│ESTABLISHED
    ▽ ▽

    问题在于用于建立TCP连接的3向握手的详细信息以及监听套接字上的传入连接队列。有关详细信息,请参见此 excellent article,本文提供了以下许多解释。

    在Linux中,实际上有两个队列用于传入连接。当服务器收到连接请求( SYN数据包)并转换为 SYN-RECEIVED状态时,此连接将放置在 SYN队列中。如果接收到相应的 ACK,则将连接放置在接受队列中,以供应用程序使用。 {backlog, N}gen_tcp:listen/2(默认值:5)选项确定访问队列的长度。

    当服务器在接受队列已满时接收到 ACK时,基本上会忽略 ACK,并且不会将 RST发送给客户端。有一个与 SYN-RECEIVED状态相关联的超时:如果未收到 ACK(或被忽略,如此处的情况),则服务器将重新发送 SYN-ACK。然后,客户端重新发送 ACK。如果应用程序在达到 SYN-ACK重试的最大次数之前已使用了接受队列中的条目,则服务器最终将处理重复的 ACKs之一,并转换为 ESTABLISHED状态。如果已达到最大重试次数,则服务器将向客户端发送 RST以重置连接。

    回到并行启动大量连接时观察到的行为。原因是,服务器上的接受队列填满的速度快于我们的应用程序消耗接受的连接的速度。一旦接收到第一个 gen_tcp:connect/3,客户端上的 SYN-ACK调用就会成功返回。连接不会立即重置,因为服务器会重试 SYN-ACK。服务器不会将这些连接报告为成功,因为它们仍处于 SYN-RECEIVED状态。

    在BSD派生的系统(包括Mac OS X)上,进入连接的队列有些不同,请参见上述 article

    关于sockets - 与gen_tcp并行建立大量连接时出现CLOSED错误(错误?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37918971/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com