如何检测套接字连接何时丢失?

Posted

技术标签:

【中文标题】如何检测套接字连接何时丢失?【英文标题】:How to detect when socket connection is lost? 【发布时间】:2012-08-18 22:45:46 【问题描述】:

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

问题是客户端无法检测到是否发生网络问题并且套接字连接消失了。 我使用了 IO::Async,也尝试了 IO::Socket。建立初始连接后,句柄始终“已连接”。

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

我正在考虑创建某种“keepAlive”,它每 X 秒“ping”(syswrite)套接字(如果没有新消息通过套接字)来检查连接是否仍然存在。

这是正确的方法吗,还是可能有另一种更有创意或更清洁的解决方案?

【问题讨论】:

我认为您所说的“心跳”程序是解决此问题的唯一已知方法。我向你保证,它非常干净和有创意。 ) 【参考方案1】:

您可以设置SO_KEEPALIVE 套接字选项,对于 TCP,该选项会定期发送保活消息,并且可能有助于检测这种情况。如果检测到这种情况,您将收到一个 EOF 条件(很可能导致包含 IO::Async::Stream 触发 on_read_eof)。

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

【讨论】:

有没有一种很好的方法可以将 SO_KEEPALIVE 直接传递给 IO::Async (Loop)? 不是直接的,但是给定套接字句柄,您可以 $sock->setsockopt(SOL_SOCKET, SO_KEEPALIVE, 1); 默认保活间隔为两小时。如果保持活动失败,您将收到“重置”条件,而不是 EOS。 公平点。你必须把间隔调短一些。有一些特定于 Linux 的 TCP 套接字选项。【参考方案2】:

简短的回答是在 perl 中没有自动检测丢弃的套接字的默认方法。

您的 ping 方法可能会很有效;您可以在后台运行一个发送 ping 请求的连续线程,如果它没有收到响应,则可以通知主线程并重新连接。

如果你想弄得一团糟,你可以使用 select() 来检测保持活动消息;但是,这可能需要一些操作系统配置,具体取决于您的平台。

更多详情请参阅此主题:http://www.perlmonks.org/?node_id=566568

【讨论】:

正如我上面所说,SO_KEEPALIVE 选项通常可以很好地检测到这种事情。此外,对于应用程序级别的 ping 支持,IO::Async 已经拥有诸如周期性计时器之类的实体,这将有助于实现这一目标。 IO::Async::Timer::Periodic 看起来是 ping 服务器的好方法

以上是关于如何检测套接字连接何时丢失?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用java套接字编程知道网络何时关闭

Perl-我如何知道套接字客户端何时断开连接(当用户关闭窗口/浏览器时)

SocketIO + Flask 检测断开连接

检测 TCP 何时拥塞 python 扭曲套接字服务器

TCP套接字服务器如何判断从客户端接收到的数据何时完成?

c#SslStream的read()函数如何知道何时返回0?