识别套接字客户端的远程断开连接

3

如何在套接字客户端程序中判断远程连接是否断开(例如,服务器宕机)。当我做一个 recv 并且服务器已经关闭时,如果没有设置任何超时,它会被阻塞。然而在我的情况下,我无法设置可靠的超时值来解决这个问题,因为否则即使服务器正常运行但响应时间比我设置的超时值更长时,recv 也会超时。


你在TCP之上使用哪个协议?没有“一种正确的方法”来做这件事。这取决于你正在实现哪个特定的协议。遵循协议的规则。 - David Schwartz
我正在使用ZeroMQ。我也在他们的论坛上提出这个问题,看看是否有这样的规定。 - Sameer Mahajan
2个回答

3
不幸的是,ZeroMQ只是把这个问题传递给下一层。因此,你在ZeroMQ之上实现的协议必须处理这个问题。建议使用心跳。基本上,如果连接空闲,只需让一方发送一条消息。另一方可以将缺少这些消息视为故障,并关闭连接。你可能希望修改更高级别的协议以提高其鲁棒性。例如,你可以提交一个命令,查询它的状态,并允许另一方忘记该命令。这样,如果连接断开,你可以重新连接并查询任何未完成的命令。任何没有的命令,你就知道没有得到通过,并可以重新提交。一旦收到带有命令结果的回复,你就可以告诉另一方现在可以忘记响应了。这样,你就可以在长时间运行的命令正在进行时保持连接活动状态。每隔一段时间你会问:“一切都还好吗?”另一方会回答:“是的”。你可以使用长轮询,让另一方在命令处理过程中延迟响应一秒左右。这样可以立即返回结果,而无需等待下一次查询。具体细节取决于你的实际要求,但你必须正确地将其设计到你的协议中。

0

如果远程主机在不发送tcp FIN包的情况下崩溃,则无法检测到此问题。您可以通过在已建立该端口的连接之后将端口防火墙化来测试该行为。您的程序将永远“挂起”。

然而,Linux内核支持一种名为TCP keep alives的机制,旨在在给定的超时时间后关闭tcp连接。如果您无法为应用程序指定超时时间,则没有可靠的机会使用该功能。最后的机会可能是使用应用程序协议的功能(您能否命名它?),如果该协议不支持连接处理功能,则可以在其上自行“发明”一些东西。


如果协议没有解决这个明显、众所周知和深入理解的问题,那么该协议就是根本性有缺陷的,应该被废弃。 - David Schwartz
我正在使用ZeroMQ。我也在他们的论坛上提出这个问题,看看是否有这样的规定。 - Sameer Mahajan
这是他们的网站:http://zeromq.org/,这是他们关于API参考的文档:http://api.zeromq.org/。我尝试查看他们的TCP KEEP ALIVE选项,但目前还无法弄清楚太多信息。 - Sameer Mahajan
@user33804 他们以前建议的和我一样 - 使用保持连接功能 - 但似乎在那之后他们实现了一个“心跳”功能。 - hek2mgl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接