Python - 如何检查套接字是否仍然连接

AK_*_*AK_ 7 python sockets networking tcp tcpclient

我有以下代码,这是不言自明的:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(host, port)
s.send("some data")
# don't close socket just yet... 
# do some other stuff with the data (normal string operations)
if s.stillconnected() is true:
    s.send("some more data")
if s.stillconnected() is false:
    # recreate the socket and reconnect
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(host, port)
    s.send("some more data")
s.close()
Run Code Online (Sandbox Code Playgroud)

如何实现s.stillconnected() 我不想盲目地重新创建套接字。

Rob*_*cia 9

如果服务器连接不再活动,调用 send 方法将抛出异常,因此您可以使用 try-exception 块尝试发送数据,如果抛出异常则捕获该异常,并重新建立连接:

try:
    s.send("some more data")
except:
    # recreate the socket and reconnect
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(host, port)
    s.send("some more data")
Run Code Online (Sandbox Code Playgroud)

编辑:根据@Jean-Paul Calderone 的评论,请考虑使用sendall方法,它是发送所有数据或抛出错误的send高级方法,而不是,它是不保证所有数据传输的低级方法数据,或者使用更高级别的模块,例如可以处理套接字生命周期的 HTTP 库。

  • 不要忘记“send”不能保证发送传递给它的整个字节字符串。调用“send”而不检查返回值(它告诉您发送了多少字节)基本上总是错误的。 (3认同)
  • `sent_length = socket.send(data); 如果 sent_length < len(data): some_retransmit_logic()`。或者`socket.sendall(data)`,它内置了重传逻辑。 (2认同)
  • 或者可能使用比套接字模块更高级别的模块,因为在 99.9% 的项目中实际上不需要重新实现低级别套接字逻辑。 (2认同)
  • 非常非常糟糕的是没有列出您所排除的错误。至少以防万一使用“ except Exception as error”或“ except BaseException as error”,即使您不感兴趣捕获它但至少登录DEBUG级别 (2认同)

Mic*_*rov 5

我用这个变体得到了很好的结果来检查套接字是否关闭(如果你想检查它是否仍然连接,则否定结果):

import logging
import socket


logger = logging.getLogger(__name__)


def is_socket_closed(sock: socket.socket) -> bool:
    try:
        # this will try to read bytes without blocking and also without removing them from buffer (peek only)
        data = sock.recv(16, socket.MSG_DONTWAIT | socket.MSG_PEEK)
        if len(data) == 0:
            return True
    except BlockingIOError:
        return False  # socket is open and reading from it would block
    except ConnectionResetError:
        return True  # socket was closed for some other reason
    except Exception as e:
        logger.exception("unexpected exception when checking if a socket is closed")
        return False
    return False
Run Code Online (Sandbox Code Playgroud)