如何检测套接字断开?/ 如何在调用socket.recv时设置超时?
我正在使用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="")