python - 是否可以在 Python 中检测 TCP 套接字断开连接?
问题描述
我正在试验 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 的问题。
更新:对于任何感兴趣的人,这就是我最终得到的。可以进行一些改进,例如添加if __name__ == "__main__"
和处理超过 1024 字节的消息,但就让客户端连接和检测它们是否消失而言,它似乎工作得很好。
解决方案
TCP 连接长时间不传输任何类型的数据是完全可以的。如果电缆断开连接也不是问题,只要重新连接以后需要传输数据即可。
确保对等点仍然可访问的唯一方法是进行某种心跳。这可以在应用程序级别完成,也可以在 TCP 级别完成 - 使用 TCP keep-alive。通常系统提供了一种方法,不仅可以启用每个套接字的 TCP 保持连接,还可以调整当套接字空闲时发送保持连接数据包的频率,即应用程序可以多快发现对等方不再存在. 要了解如何在 Python 中执行此操作的详细信息,请参阅如何使用 python 脚本更改 tcp keepalive 计时器?.
推荐阅读
- c# - 在 C# 中带有 expando 对象的字段'params'
- docker - 为什么 Docker 找不到现有的包?
- python - Python中整数的Hashtag
- php - php max_execution_time 在 laravel 应用程序中不起作用
- android - 当浮动标签被提升时如何在textinputlayout上添加信息图标
- typescript - TypeScript 如何支持这种类型的 Generic Type?
- c# - 从 JSON 对象获取嵌套的 fieldNames
- drupal - 尝试访问某些管理页面时收到“请求被拒绝”响应
- wpf - MVVM WPF 中我的 ScrollViewer 的 OnScrollChanged 事件
- mysql - 根据产品名称获取最高平均价格