25

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

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

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

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

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

对此有何建议?

4

1 回答 1

28

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

如果一个套接字在输出可读列表中,您可以确定该套接字上的 recv 将返回某些内容。可写列表的想法相同。你将能够发送一些东西。也许不是你想要的,但有总比没有好。(实际上,任何相当健康的套接字都将返回为可写的——这只是意味着出站网络缓冲区空间可用。)

...如果在这些套接字的输入列表中的某个地方已经死了一个令人讨厌的死亡,则选择将失败。

(最后一段在 Python 3 版本中不再存在。)

这是我通常使用的流程

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(f'received: {recv}')
    if len(ready_to_write) > 0:
        # connection established, send some stuff
        conn.send('some stuff')
于 2014-02-15T20:07:47.867 回答