当socket连接丢失时如何检测?

4
我有一个脚本(我现在没有代码示例,但我使用了IO :: Async),它会连接到远程服务器上的套接字并监听。客户端通常只需等待新数据。

问题在于,如果发生网络问题并且套接字连接消失,客户端无法检测到。我尝试过使用IO::Async和IO::Socket,但是在初始连接建立后,处理句柄始终处于“连接”状态。

如果重新建立网络连接,则套接字连接自然仍然丢失,因为脚本不知道应该重新连接。

我考虑创建一种“keepAlive”,每隔X秒钟“ping”(syswrite)套接字(如果没有通过套接字传输任何新内容),以检查连接是否仍然存在。

这是正确的方法吗?或者还有其他更具创意或更干净的解决方案吗?


我认为你所说的“心跳”程序是目前已知的解决此问题的唯一方法。它非常干净和创新,我向你保证。 - raina77ow
2个回答

5

您可以设置SO_KEEPALIVE套接字选项,对于TCP,它会发送周期性的keepalive消息,并且可能有助于检测此条件。如果检测到此条件,您将收到EOF条件(最有可能导致包含IO::Async::Stream触发on_read_eof)。

对于更好的解决方案,您可以考虑某种应用程序级别的keepalive消息,例如IRC的PING命令。


有没有比较好的方法可以直接将SO_KEEPALIVE传递给IO::Async(Loop)? - toktok
不是直接的,但是通过给定的套接字句柄,你可以使用 $sock->setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1); 来实现。 - LeoNerd
默认的保持连接间隔为两个小时。如果保持连接失败,您将收到一个“重置”条件,而不是EOS。 - user207421
一个很好的观点。你需要将间隔时间缩短到更短的时间。有一些针对Linux特定的TCP套接字选项可以实现这个功能。 - LeoNerd

3
短答案是,Perl中没有默认的自动检测丢失套接字的方法。您的ping方法可能非常有效;您可以在后台运行连续线程发送ping请求,如果没有收到响应,则可以通知主线程并发出重新连接。如果您想弄乱,可以使用select()来检测保持活动消息;但是,这可能需要一些操作系统配置,具体取决于您的平台。有关详细信息,请参见此线程:http://www.perlmonks.org/?node_id=566568

1
正如我之前所说,SO_KEEPALIVE选项通常在检测此类问题时表现良好。此外,对于应用程序级别的ping支持,IO::Async已经拥有了周期定时器等实体,这将有助于解决该问题。 - LeoNerd
IO::Async::Timer::Periodic 看起来是一个很好的ping服务器的方式。 - toktok

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