sock.recvfrom
能否从读取器处引发 BlockingIOError
?比如下面这样
sock.setblocking(False)
def reader()
try:
(data, addr) = sock.recvfrom(512)
except BlockingIOError:
# Can this ever be raised?
loop.add_reader(sock.fileno(), reader)
同样,sock.send
是否可以从编写器处引发 BlockingIOError
?
sock.setblocking(False)
def writer()
try:
bytes_sent = sock.send(data)
except BlockingIOError:
# Can this ever be raised?
loop.add_writer(sock.fileno(), writer)
我尝试过发送/接收相当多的数据,但到目前为止从未发生过。从逻辑上讲,它永远不会真正发生吗?如果可能发生,在什么情况下发生?
最佳答案
Can [
BlockingIOError
in an asyncio reader] never actually happen, logically? If if it can happen, under what circumstances?
这个问题的答案几乎肯定取决于系统。 Python 本身不提供任何保证:像 os.read 和 socket.recv 这样的函数只是检查底层系统调用返回的值,如果它表明错误,继续将系统提供的错误转换为Python异常。
因此,问题归结为,如果前面的 poll/select 表明它是可读的(以及写入的等效项),则从套接字读取是否会失败,并出现 EAGAIN 或等效的情况。虽然这听起来确实是一种异常情况,但 select(2)
man page 明确在BUGS下发出警告:
Under Linux,
select()
may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to useO_NONBLOCK
on sockets that should not block.
对于非阻塞套接字,应将“尽管如此,后续读取会阻塞”解读为“尽管如此,后续读取会因 EAGAIN
失败”,并且该警告适用于该问题。该问题也不是 select()
特有的; poll(2)
man page在其 BUGS 部分还提到了虚假唤醒,请参阅 select(2)
手册了解详细信息。
换句话说,可移植代码不应依赖于从不引发 BlockingIOError
的“可读”套接字读取。 Asyncio 不依赖它:它通过简单地 not completing the future 对 EAGAIN
作出 react 。 ,从而重新挂起等待读取的协程。
关于python - 非阻塞套接字可以从读取器/写入器引发 BlockingIOError 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55625684/