当我在OSX10.9.1上使用Python3.3实现RUDP时,我注意到以下代码实际上并不像在Linux上那样工作:(不管是哪种语言,C、Java和C#/Mono的行为都相同)
from socket import *
udp = socket(AF_INET, SOCK_DGRAM)
udp.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
udp.bind(('0.0.0.0', 1337))
udp.setblocking(False)
udp.setsockopt(SOL_IP, IP_TTL, 4)
udp.connect(('8.8.8.8', 12345))
buf = b'x' * 400
for _ in range(1024 * 1024 * 10):
udp.send(buf)
这段代码只是不断向8.8.8.8发送大量的udp数据包,这些数据包在经过4个跳点后就会被丢弃,因此它们不应该到达目的地,这只是为了模拟出站流量。
问题:
该代码在Linux(Windows也是如此)上抛出BlockingIOError错误,这是可以接受的,因为它是一个非阻塞套接字。但是在OSX上,它会抛出OSError(55, 'No buffer space available')错误,这是不好的。
但真正有趣的事情是,即使我将此套接字置于阻塞模式,这段代码在OSX上仍然会抛出错误。而在Linux和Windows上,这根本没有抛出任何错误,就像预期的那样,它只会阻塞。
这是基于BSD的系统的实现细节吗?还是我错过了一些重要的网络设置?
[编辑]
我忘记提到我是在千兆局域网中测试这种行为的。我认为这就是问题所在。我连接到了一个100mbit网络,问题消失了,甚至在300mbit WLAN上也没有出现问题。
现在我认为这是连接到高速网络时OSX特有的行为。
[编辑-最终]
我终于找到了原因:
http://lists.freebsd.org/pipermail/freebsd-hackers/2004-January/005369.html
在BSD系统上,sendto永远不会阻塞,文档是错误的。再加上连接高速局域网时出现的一些OSX特定问题。总体而言:不要认为sendto会阻塞,在BSD上它不会。好处是:如果你知道这一点,你可以考虑这个问题。