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

标签 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 内置到协议(protocol)中,但正常超时是由操作系统设置的,不可调整,并且是几个小时,不应依赖。

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

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

最佳答案

TCP 连接长时间不传输任何类型的数据是完全可以的。即使电缆断开也没有问题,只要稍后需要传输数据即可重新连接。

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

关于python - 是否可以在 Python 中检测 TCP 套接字断开连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53471205/

相关文章:

python - 在 open() 函数中包含 'r' 的目的是什么?

php - Apache:支持 [PHP|Python|Ruby] 的虚拟主机

sockets - WinRT 写入 TCP 流不起作用

python - 如何在不阻塞父进程的情况下在python子进程中运行?

sockets - 使用 TCP/IP LabVIEW 在 PC 和 UR5 Universal Robotics 机器人 ARM 之间进行通信

python - DateTimeField 在 Django 管理中没有日期选择器

python - 重置 time.clock()

java - 如何在 Socket 游戏服务器上组织命令/处理程序?

java - 连接两个客户端而不使用端口转发

linux - 如何拒绝除ip 192.168.0.36以外的所有人访问服务器的80端口?