是否可以在 Python 中检测 TCP 套接字断开连接? [英] Is detecting a TCP socket disconnect in Python possible?

查看:509
本文介绍了是否可以在 Python 中检测 TCP 套接字断开连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在试验 Python 的 socketserver.TCPServer,看看它是如何工作的.

I'm experimenting with Python's socketserver.TCPServer, to see how it works.

我想我已经弄清楚了大部分事情,但仍然存在的一个问题是如何检测突然的客户端断开连接,以及是否有可能.

I think I have most things figured out, but the one question that remains is how to detect sudden client disconnects, and if it's even possible.

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

What I've seen so far is that if I write a simple TCPServer, and connect to it with telnet, once telnet disconnects, the TCPServer knows that the client disconnected. Clearly, it gets a TCP message that tells it the client is disconnecting. That's great.

我更进一步,我没有关闭客户端上的 telnet 进程,而是向它发送了一个 SIGKILL,以终止该进程,甚至不让它清理(告诉服务器它正在断开连接).即便如此,服务器也知道客户端马上离开了.似乎客户端的操作系统 - 而不是 telnet 进程 - 发送 TCP FIN/RST 消息来告诉服务器客户端已经消失.也很棒.

I went one step further, and instead of closing the telnet process on the client, I sent it a SIGKILL, to kill the process without even letting it clean up (tell the server it's disconnecting). Even then, the server knows that the client left right away. It seems that the OS of the client - not the telnet process - sends the TCP FIN/RST message to tell the server the client is gone. Also great.

接下来,我更进一步,当 telnet 客户端连接到我的 TCPServer 时,我告诉客户端上的 iptables 停止与服务器通信.现在,绝对没有消息被发送到服务器告诉它客户端消失了.此时,我的 TCPServer 无法判断客户端已离开.

Next, I went one step beyond that, and while the telnet client was connected to my TCPServer, I told iptables on the client to stop talking to the server. Now, there was absolutely no message being sent to the server to tell it that the client disappeared. At this point, my TCPServer couldn't tell that the client had left.

我知道我可以设置 socket.setdefaulttimeout() 来阻止 recv() 无限期地阻塞等待来自客户端的消息.这样做的问题是,如果客户端只是保持安静一段时间(不向服务器发送任何消息),或者客户端突然消失,则会触发超时.

I know that I can set a socket.setdefaulttimeout() to stop a recv() from blocking indefinitely waiting for a message from the client. The trouble with that is that the timeout will be triggered if the client just stays quiet for a while (doesn't send the server any messages), or if the client disappears all of a sudden.

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

So my question is this: when a socket is connected between a server and a client, and the client disappears completely, without sending a TCP FIN or RST, does the server have any way of knowing that the client is gone (as opposed to still there, but not sending any messages)? Or is having some sort of heartbeat that the client would stop responding to the main way to tell that the client is gone?

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

I read somewhere that TCP has keepalive built into the protocol, but that the normal timeout for that is set by the OS, not adjustable, and is hours, and should not be relied upon.

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

While I'm currently working with Python, I imagine this is more of a generic networking question than Python-specific.

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

Update: For anyone interested, this is what I ended up with. There's a few improvements that could be made, like adding if __name__ == "__main__", and handling messages longer than 1024 bytes, but as far as letting clients connect, and detecting if they disappear, it seems to work pretty well.

推荐答案

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

It is perfectly fine for TCP connections to not transfer any kind of data for a long time. And it is also not a problem if a cable gets disconnected as long as it is reconnected later data need to be transmitted.

确保对等点仍然可访问的唯一方法是拥有某种心跳.这可以在应用程序级别完成,也可以在 TCP 级别完成 - 使用 TCP keep-alive.通常,系统提供了一种方法,不仅可以为每个套接字启用 TCP 保持连接,而且还可以调整套接字空闲时保持连接数据包的发送频率,即应用程序可以多快地发现对等方不再存在.要详细了解如何在 Python 中执行此操作,请参阅 How使用python脚本更改tcp keepalive计时器?.

The only way to be sure that the peer is still reachable is to have some kind of heartbeat. This can be either be done at the application level or it can be done at the TCP level - using TCP keep-alive. Usually systems offer a way to not only enable TCP keep-alive per socket but also to adjust how often a keep-alive packet will be send when the socket is idle, i.e. how quick an application can find out that the peer is no longer there. To get to the details on how to do this in Python see How to change tcp keepalive timer using python script?.

这篇关于是否可以在 Python 中检测 TCP 套接字断开连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆