如何检测套接字断开?/ 如何在调用socket.recv时设置超时?

4 投票
2 回答
6105 浏览
提问于 2025-04-16 17:40

我正在使用gevent修补过的socket来连接一个流媒体服务器,并且我用的是ADSL网络。

我并不控制这个服务器,但在我的测试中,如果我停止服务器,我可以通过检查recv的结果是否是空字符串来发现断开连接。但是如果我把ADSL调制解调器关掉,recv就一直不结束。如果我只是拔掉电脑的网络线,它也不会返回空字符串,不过当我重新连接时,它会把这段时间服务器发送的所有内容都返回给我。所以我猜测是路由器或调制解调器在帮我保持连接,并在我拔掉网络线的时候缓存流数据。

我尝试把socket.SO_RCVTIMEO设置为几秒钟,但它并没有检测到断开连接,recv依然会一直“阻塞”下去。这是gevent,所以它只会阻塞这个绿色线程,但我需要尽快检测到断开连接,这样我才能尝试重新连接。

2 个回答

2

它没有检测到断开连接,因为实际上并没有断开连接,TCP“连接”仍然是活着的,并且应该是可靠的。比如说,如果你拔掉了网线,然后再插上,连接还是会继续工作的。

如果你真的想尽快检测到断开连接,那我想你可以每秒检查一次操作系统的网络状态(使用ifconfig或ipconfig),或者使用操作系统的事件,当你检测到网络断开时就可以执行你想做的事情。

4

使用gevent提供的超时功能,比如在一个with语句中:

with Timeout(5, False):
    data = sock.recv()

或者作为一个函数:

data = gevent.with_timeout(5, sock.recv, timeout_value="")

撰写回答