首页 > 解决方案 > 强制非阻塞 UDP 套接字在 sendto 上引发 BlockingIOError

问题描述

我相信非阻塞 UDP 套接字可以在 sendto 上引发 BlockingIOError。我想强制这种情况来测试我的程序在这种情况下的行为。

sock = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
sock.setblocking(False)
sock.bind(('', 7777))
...
# Even if repeating in a loop, doesn't seem to raise a BlockingIOError
sock.sendto(b'abcde', ('1.2.3.4', 61908))

我尝试将传出缓冲区设置为小

buffer_size = 5
sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, buffer_size)

但它要么似乎没有影响,要么导致OSError: [Errno 40] Message too long缓冲区小于数据。

我的信念是错误的:它永远不会引发 BlockingIOError 吗?或者如果可以,我该如何强制?

我的目标是进行集成式测试:我想实际拥有一个真正的套接字并进行实际的网络调用。在这种情况下模拟单元式测试的套接字并不理想。

套接字只能在单线程 Python asyncio 程序中使用。

标签: pythonlinuxsocketsudpnonblocking

解决方案


摘自 C 语言中的 TCP/IP 套接字:程序员实用指南,Michael J. Donahoo,Kenneth L. Calvert

对于 UDP 套接字,没有发送缓冲区,因此send()永远sendto()不会返回EWOULDBLOCK

https://linux.die.net/man/2/sendto有一个关于为什么的提示......

当设备队列溢出时,数据包会被静默丢弃。

因此,在 Python 术语中,BlockingIOError至少在 Linux 上不能提出。


推荐阅读