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

标签 python linux python-3.x sockets python-asyncio

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 use O_NONBLOCK on sockets that should not block.

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

换句话说,可移植代码不应依赖于从不引发 BlockingIOError 的“可读”套接字读取。 Asyncio 不依赖它:它通过简单地 not completing the futureEAGAIN 作出 react 。 ,从而重新挂起等待读取的协程。

关于python - 非阻塞套接字可以从读取器/写入器引发 BlockingIOError 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55625684/

相关文章:

linux - 如何在 Linux/Unix 上递归复制以 "abc"开头的目录?

python - 当我们在 tkinter 的 Text 小部件中清除它时,如何从列表中删除一个值?

linux - 使用Cloud9 iDE与AWS交互是否是强制性的?

python - python if/else 中的列表理解

python - 使用 PyQt4 和 python 3.5.2 运行 PyMoskito 示例时出错

python - 嵌入式 python : extern PyRun_SimpleString, 预期标识符

python - 使用 Pandas 计算累积平均值

python - 使用 Python 就地重写文件

python - 在 docker-compose 中运行 python selenium

c++ - 如何使用 C++ 不使用 system() 删除除最后 10 个文件之外的所有文件