繁体   English   中英

非阻塞套接字可以从读取器/写入器引发 BlockingIOError 吗?

[英]Can a non-blocking socket raise BlockingIOError from a reader/writer?

sock.recvfrom可以从读者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是否可以从作者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)

我已经尝试发送/接收相当多的数据,但到目前为止从未发生过。 从逻辑上讲,它真的永远不会发生吗? 如果可以,在什么情况下发生?

[ BlockingIOError in a asyncio reader] 从逻辑上讲,真的永远不会发生吗? 如果可以的话,是在什么情况下发生的?

这个问题的答案几乎肯定取决于系统。 Python 本身不提供任何保证: os.readsocket.recv类的函数只检查底层系统调用返回的值,如果它指示错误,继续将系统提供的错误转换为蟒蛇异常。

因此,问题归结为如果前面的轮询/选择表明它是可读的(以及写入的等效项),那么从套接字读取是否会因EAGAIN或等效项而失败。 虽然这听起来像是一种异常情况,但select(2)手册页在 BUGS 下明确警告了它:

在 Linux 下, select()可能会将套接字文件描述符报告为“ready for reading”,但随后的读取会阻塞。 例如,当数据已到达但检查时校验和错误并被丢弃时,可能会发生这种情况。 可能还有其他情况,其中文件描述符被虚假地报告为就绪。 因此,在不应阻塞的套接字上使用O_NONBLOCK可能更安全。

对于非阻塞套接字,应该将“尽管如此,随后的读取阻塞”读作“尽管如此,随后的读取失败并使用EAGAIN ”,并且警告适用于这个问题。 这个问题也不是特定于select() poll(2)手册页还在其 BUGS 部分提到了虚假唤醒,有关详细信息,请参阅select(2)手册。

换句话说,可移植代码不应依赖于从不会引发BlockingIOError “可读”套接字读取。 Asyncio 不依赖它:它通过简单地不完成 future来对EAGAIN做出反应,从而重新挂起等待读取的协程。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM