异步接收是否保证检测到连接失败?

Fra*_*lli 3 connection nio tcp boost-asio

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

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

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

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

非常感谢你.

Ber*_*t F 5

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

当连接的发送方以某种方式不再知道网络连接时,会出现问题.例如,这可能发生在

  • 发送OS突然终止/重启(停电,OS故障/ BSOD等).

  • 当双方之间发生网络中断并清理其侧面时,发送侧关闭其侧面:例如,在中断期间发送操作系统干净地重新启动,传输Windows操作系统从网络中拔出

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

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

  • 谢谢你,你给我所说的确切问题起了个名字,并提供了详细的解释.我现在可以理解,异步与它无关.我读过关于TCP keepalive功能的负面评论,所以我想我会坚持自定义应用程序层ping. (2认同)