OS X UDP发送错误:55没有可用的缓冲区空间

时间:2014-02-23 19:54:05

标签: python c linux macos sockets

当我在OSX10.9.1上的python3.3中实现RUDP时,我注意到以下代码实际上并没有像它在linux上那样做:(无论哪种语言,C,Java和C#的相同行为都无关紧要单声道)

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)

这段代码只是将大量udp数据包写入8.8.8.8,这些数据包在4跳后丢失,因此它们不应该到达目的地,只是为了模拟传出流量。

问题:

此代码抛出一个OSError(55,'没有可用缓冲区空间')错误,而在Linux(Windows也是如此)上它会抛出一个BlockingIOError,这很好,因为它是一个非阻塞套接字。

因此,在Linux和Windows上,套接字在OSX上运行正常,这是一个OSError,这很糟糕。

但真正有趣的是,即使我将此套接字置于阻塞模式,此代码仍会在OSX上引发错误。在Linux和Windows上,这根本不会引发任何错误,正如预期的那样,它只会阻塞。

这是基于BSD的系统的实现细节吗?或者我错过了一些重要的网络设置?

[编辑]

我忘了提到我在千兆位局域网中测试这种行为。我认为这就是问题所在。我连接到一个100mbit的网络,问题就消失了,即使300mbit wlan问题也没有发生。

现在我认为这是连接到高速网络时的一些OSX特定行为。

[编辑 - 决赛] 我终于找到了原因:

http://lists.freebsd.org/pipermail/freebsd-hackers/2004-January/005369.html

在BSD系统发送到NEVER块时,文档是错误的。当连接到高速兰特时混合了一些OSX特定问题。总的来说:只是不要认为sendto块,它不在BSD上。好事:如果你知道,你可以考虑到这一点。

2 个答案:

答案 0 :(得分:2)

我认为你不想绑定套接字。这应该只在您计划收听的服务器端完成。如果你放弃绑定调用会发生什么?例如:

from socket import *
import time

udp = socket(AF_INET, SOCK_DGRAM)

buf = b'x' * 400
for _ in range(1024 * 1024 * 10):
    while True
        try:
            udp.sendto(buf, ('8.8.8.8', 12345))
            break
        except OSError, exc:
            if exc.errno == 55:
                time.sleep(0.1)
            else:
                raise

答案 1 :(得分:-1)

我也能够在这个相关的SO问题中看到这个OSX问题:Non-blocking DatagramChannel throws SocketException ("No buffer space available") on OSX but UDP packet is still successfully sent in full

感觉就像一个bug。

相关问题