Python:检测套接字何时因任何原因断开连接?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17386487/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 08:04:13  来源:igfitidea点击:

Python: detect when a socket disconnects for any reason?

pythonsockets

提问by fdmillion

I'm writing an app in Python 2.7.5 using the raw socket interface (import socket).

我正在使用原始套接字接口 ( import socket)在 Python 2.7.5 中编写应用程序。

I need to know if there's a way I can either register some sort of event, or easily test at a regular interval, if a TCP socket connection is still connected and established.

我需要知道是否有一种方法可以注册某种事件,或者轻松地定期测试,如果 TCP 套接字连接仍然连接并建立。

Most of the advice I've found says things like "just try to read from it; if it's closed you'll get an error or no bytes." However, sometimes I'm not ready to readfrom it but I still want to know if the socket gets closed, so for example I can manually reconnect immediately.

我发现的大多数建议都说“只是尝试从中读取;如果它关闭,您将收到错误或没有字节。” 但是,有时我还没有准备好,read但我仍然想知道套接字是否关闭,因此例如我可以立即手动重新连接。

Also, reading from the socket would remove the bytes read from the buffer, so reading simply to test for connection "liveness" doesn't seem feasible.

此外,read从套接字 ing 会删除从缓冲区读取的字节,因此read仅测试连接“活跃度”似乎不可行。

Having a background thread to check for connection liveness would be OK with me. That thread could check say once per second to see if the connection is live; if it is dropped, then it could call a function, or set a variable or some other thing so that the app knows the connection closed. Knowing WHY it closed (reset by peer, timeout, etc) would be even more useful....

有一个后台线程来检查连接活跃度对我来说没问题。该线程可以每秒检查一次以查看连接是否有效;如果它被删除,那么它可以调用一个函数,或设置一个变量或其他一些东西,以便应用程序知道连接已关闭。知道它为什么关闭(由对等重置、超时等)会更有用....

Any advice on this?

对此有何建议?

回答by Steve Zhan

Use selectlike this tutorial suggested http://docs.python.org/2/howto/sockets.html#non-blocking-sockets

使用select本教程建议 http://docs.python.org/2/howto/sockets.html#non-blocking-sockets

If a socket is in the output readable list, you can be as-close-to-certain-as-we-ever-get-in-this-business that a recv on that socket will return something. Same idea for the writable list. You'll be able to send something. Maybe not all you want to, but something is better than nothing. (Actually, any reasonably healthy socket will return as writable - it just means outbound network buffer space is available.)

... if somewhere in those input lists of sockets is one which has died a nasty death, the select will fail.

如果一个套接字在输出可读列表中,您可以非常确定,因为我们曾经在这个业务中获得过该套接字上的 recv 将返回一些东西。可写列表的想法相同。你将能够发送一些东西。也许不是您想要的全部,但有总比没有好。(实际上,任何合理健康的套接字都会以可写形式返回——这仅意味着出站网络缓冲区空间可用。)

...如果在这些输入套接字列表中的某个地方是一个不幸死亡的套接字,则选择将失败。

This is the flow I usually use

这是我通常使用的流程

import select
import socket

ip = '127.0.0.1'
port = 80

conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((ip, port))

while True:
    try:
        ready_to_read, ready_to_write, in_error = \
            select.select([conn,], [conn,], [], 5)
    except select.error:
        conn.shutdown(2)    # 0 = done receiving, 1 = done sending, 2 = both
        conn.close()
        # connection error event here, maybe reconnect
        print 'connection error'
        break
    if len(ready_to_read) > 0:
        recv = conn.recv(2048)
        # do stuff with received data
        print 'received:', recv
    if len(ready_to_write) > 0:
        # connection established, send some stuff
        conn.send('some stuff')