是否可以在Python中检测到TCP套接字断开连接?

时间:2018-11-25 19:43:38

标签: python sockets networking

我正在尝试使用Python的socketserver.TCPServer,以了解其工作原理。

我想我已经弄清楚了大多数事情,但是剩下的一个问题是如何检测客户端突然断开连接,以及是否有可能。

到目前为止,我所看到的是,如果我编写一个简单的TCPServer,并使用telnet连接到它,一旦telnet断开连接,TCPServer就会知道客户端已断开连接。显然,它会收到一条TCP消息,告知客户端正在断开连接。太好了。

我又走了一步,而不是关闭客户端上的telnet进程,而是给它发送了SIGKILL,以杀死该进程而没有清理干净(告诉服务器它正在断开连接)。即使那样,服务器也知道客户端马上离开了。客户端的操作系统(而不是telnet进程)似乎发送TCP FIN / RST消息来告诉服务器客户端已消失。也很棒。

接下来,我进一步迈出了一步,当telnet客户端连接到我的TCPServer时,我告诉客户端上的iptables停止与服务器通信。现在,绝对没有消息发送到服务器来告知客户端消失了。在这一点上,我的TCPServer无法分辨出客户端已经离开。

我知道我可以设置一个socket.setdefaulttimeout()来阻止recv()无限期地阻止来自客户端的消息。麻烦的是,如果客户端只是保持一会儿安静(不向服务器发送任何消息),或者客户端突然消失,就会触发超时。

所以我的问题是这样的:当套接字在服务器和客户端之间连接并且客户端完全消失而没有发送TCP FIN或RST时,服务器是否有任何办法知道客户端已消失(如反对仍然在那里,但不发送任何消息)?还是正在产生某种心跳,使客户停止响应告诉客户已离开的主要方式?

我在某处读到TCP已在协议中内置了keepalive,但是该协议的正常超时是由操作系统设置的,不可调整,并且是数小时,因此不应依赖。

虽然我目前正在使用Python,但我想这更多是一个通用的网络问题,而不是特定于Python的问题。

更新:对于任何感兴趣的人,this就是我最终的目的。可以进行一些改进,例如添加if __name__ == "__main__",并处理长度超过1024字节的消息,但是就让客户端连接并检测它们是否消失而言,它似乎工作得很好。

1 个答案:

答案 0 :(得分:3)

TCP连接长时间不传输任何类型的数据是完全可以的。而且,只要以后重新连接电缆,只要断开电缆连接,这也不是问题。

确保对等方仍可访问的唯一方法是具有某种心跳。这可以在应用程序级别完成,也可以在TCP级别完成-使用TCP保持活动。通常,系统不仅提供一种方法来启用每个套接字的TCP保持活动状态,而且还可以调整套接字空闲时发送保持活动数据包的频率,即应用程序能够多快地发现对等方不再存在。要详细了解如何在Python中执行此操作,请参见How to change tcp keepalive timer using python script?