这个问题不仅限于Python。这是一个普通的插座问题。我有一个非阻塞套接字,并希望连接到可访问的机器 - 另一方面端口不存在。为什么选择(...)成功呢?我预计会超时。 sock.send(...)因管道损坏而失败。如何在选择(...)后确定套接字是否真正连接? 提前谢谢。
import socket, errno, os, time, select
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setblocking(0)
err = sock.connect_ex(('192.168.178.21', 12345))
ready_to_read, ready_to_write, in_error = select.select([], [sock], [], timeout=5)
#ready_to_write is set even 192.168.178.21:12345 does not exist.
sock.setblocking(1)
sock.send('foo') #this fails
sock.close()
答案 0 :(得分:4)
尝试检查返回值。以下是我在类似情况下得到的结果:
>>> import socket, errno, os, time, select
>>> sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>>> sock.setblocking(0)
>>> err = sock.connect_ex(('10.0.0.1', 12345))
>>> import errno
>>> print errno.errorcode[err]
EINPROGRESS
>>> print sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)
61
>>> print errno.errorcode[61]
ECONNREFUSED
select()
调用可能正在返回,因为套接字上存在异常情况 - 也就是说,它的连接被拒绝了。
如果我这样做,select()
会立即返回:
>>> ready_to_read, ready_to_write, in_error = select.select([], [sock], [])
有趣的是,返回值与您传入的内容完全匹配(如果您有多个套接字,那可能会有所不同):
>>> print in_error
[]
>>> print ready_to_read
[]
>>> print ready_to_write
[<socket._socketobject object at 0x10ccd0980>]
select()
的设计者期望您在循环中运行select()
,如果套接字在您尝试写入时返回错误,则在写入失败时将其从列表中删除。
所以你有几个选择,我的头脑:
getsockopt()
检查套接字是否正常,或处于错误状态。