【问题标题】:Does asynchronous receive guarantee the detection of connection failure?异步接收能保证检测到连接失败吗?
【发布时间】:2011-05-20 14:44:22
【问题描述】:

据我所知,TCP 套接字上的阻塞接收并不总是通过返回 -1 值或引发 IO 异常来检测连接错误(由于网络故障或远程端点故障):有时它可能会无限期挂起。

解决此问题的一种方法是为阻塞接收设置超时。如果接收时间的上限已知,则可以将此限制设置为超时,并且在超时到期时可以认为连接丢失;当这样的上限事先不知道时,例如在一个连接保持打开以接收发布的 pub-sub 系统中,设置的超时会有些随意,但它的到期可能会触发一个 ping/pong 请求来验证连接(以及端点)仍在运行。

我想知道使用异步接收是否还可以解决检测连接失败的问题。在 boost::asio 中,我会调用 socket::asynch_read_some() 注册一个异步调用的处理程序,而在 java.nio 中,我会将通道配置为非阻塞并将其注册到带有 OP_READ 兴趣标志的选择器。我想正确的连接失败检测意味着,在第一种情况下,将使用非 0 错误代码调用处理程序,而在第二种情况下,选择器将选择有故障的通道,但随后在通道上出现 read()要么返回-1,要么抛出IOException

异步接收是否保证了这种行为,或者是否存在连接失败后的情况,例如,在 boost::asio 中,处理程序永远不会被调用,或者在 java.nio 中,选择器永远不会选择通道?

非常感谢。

【问题讨论】:

    标签: tcp connection boost-asio nio


    【解决方案1】:

    我相信您指的是TCP half-open connection 问题(该术语的RFC 793 含义)。在这种情况下,接收操作系统永远不会收到丢失连接的指示,因此它永远不会通知应用程序。应用程序是同步读取还是异步读取不进入。

    当连接的发送端不知何故不再知道网络连接时,就会出现问题。例如,当

    • 传输操作系统突然终止/重新启动(断电、操作系统故障/BSOD 等)。

    • 发送端在两端网络中断时关闭其端并清理其端:例如,发送端操作系统在中断期间干净地重新启动,发送端Windows操作系统从网络中拔出

      李>

    当这种情况发生时,接收方可能正在等待永远不会到来的数据或 FIN。除非接收方发送消息,否则它无法实现发送方不再了解接收方。

    您的解决方案(超时)是解决问题的一种方法,但它应该包括向发送方发送消息。同样,读取是同步的还是异步的并不重要,只是它不会无限期地读取和等待数据或 FIN。另一种解决方案是使用某些 TCP 堆栈支持的TCP KEEPALIVE 功能。但是任何通用解决方案的难点通常是determining a proper timeout,因为超时高度依赖于特定应用程序的特性。

    【讨论】:

    • 谢谢,您为我正在谈论的确切问题命名并提供了详细解释。我现在可以理解异步与它无关。我读过关于 TCP keepalive 功能的负面 cmets,所以我想我会坚持使用自定义应用层 ping。
    【解决方案2】:

    由于 TCP 的工作原理,您通常必须发送数据以发现硬连接失败,从而发现永远不会返回 ACK 数据包。一些协议尝试通过定期使用保持活动或 ping 数据包来识别此类条件:如果一方在 X 时间内没有收到这样的数据包(并且可能在尝试并失败之后),它可以认为连接已死。

    要回答您的问题,阻塞和非阻塞接收应该执行相同的操作,除了阻塞本身的行为,因此两者都会遇到同样的问题。为了确保您可以检测到来自远程主机的静默故障,您必须使用我所描述的保持活动形式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 2015-06-19
      • 1970-01-01
      • 2021-08-19
      • 2015-10-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多