【发布时间】:2013-11-05 17:53:51
【问题描述】:
我有一些代码将连接到主机,除了侦听传入数据之外什么都不做,直到客户端关闭或主机发送关闭语句。为此,我的代码运行良好。
但是,当主机在没有发送关闭语句的情况下死亡时,我的客户端会按预期一直监听传入的数据。为了解决这个问题,我每隔 foo 秒设置一次套接字超时,并开始检查连接是否处于活动状态。从 Python socket howto 我发现了这个:
select 的一个非常讨厌的问题:如果在这些套接字的输入列表中的某个地方是一个已经严重死亡的套接字,则 select 将失败。然后,您需要遍历所有这些列表中的每个该死的套接字并执行 select([sock],[],[],0) 直到找到坏的。超时时间为 0 意味着它不会花费很长时间,但它很难看。
# Example code written for this question.
from select import select
from socket include socket, AF_INET, SOCK_STREAM
socket = socket(AF_INET, SOCK_STREAM)
socket.connect(('localhost', 12345))
socklist = [socket,]
attempts = 0
def check_socklist(socks):
for sock in socklist:
(r, w, e) = select([sock,], [], [], 0)
...
...
...
while True:
(r, w, e) = select(socklist, [], [], 60)
for sock in r:
if sock is socket:
msg = sock.recv(4096)
if not msg:
attempts +=1
if attempts >= 10:
check_socket(socklist)
break
else:
attempts = 0
print msg
这段文字提出了三个问题。
- 我被告知要检查连接是否处于活动状态,必须写入套接字并查看响应是否返回。如果不是,则必须假定连接已死。在文本中它说要检查错误的连接,一个单独的每个套接字,将它传递给选择的第一个参数并将超时设置为零。这将如何确认套接字是否已死?
- 为什么不通过尝试写入套接字来测试套接字是死是活?
- 当连接处于活动状态和断开连接时,我在寻找什么? Select 将立即超时,因此没有数据将证明什么都没有。
我意识到有像 gevent、asyncore 和 twisted 这样的库可以帮助我解决这个问题,但我选择自己做这件事是为了更好地了解正在发生的事情并获得更多控制权在源头上我自己。
【问题讨论】:
-
我不确定 Python howto 是否正确,必须遍历所有套接字以确定哪个套接字“死得很惨”。以我的经验,只有当你向它传递一个无效的文件描述符时,select() 才会失败,即使是远程对等端突然断开的套接字仍然是一个完全有效的套接字,直到你明确地关闭它。因此,请注意这一点。
-
@JeremyFriesner 我认为写入死套接字会发现它已死(在尝试重新传输段后,客户端将关闭套接字并将 RST 发送到服务器。
-
@Den 是的,你是对的。
标签: python sockets select tcp blocking