首页 文章

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

提问于
浏览
1

我正在试验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 回答

  • 3

    TCP连接完全可以在很长时间内不传输任何类型的数据 . 如果电缆断开连接也是一个问题,只要它重新连接以后需要传输数据 .

    确保对等方仍可访问的唯一方法是获得某种心跳 . 这可以在应用程序级别完成,也可以在TCP级别完成 - 使用TCP keep-alive . 通常,系统提供了一种方法,不仅可以为每个套接字启用TCP保持活动,还可以调整套接字空闲时保持活动数据包的发送频率,即应用程序发现对等体不再存在的速度 . 要了解如何在Python中执行此操作的详细信息,请参阅How to change tcp keepalive timer using python script? .

相关问题