Erreur d’envoi OS X UDP: 55 Pas d’espace tampon disponible

Pendant que j’implémentais RUDP dans python3.3 sur OSX10.9.1, j’ai remarqué que le code suivant ne fait pas ce qu’il fait sur linux: (peu importe la langue, le même comportement pour C, Java et 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) 

Ce code ne fait que continuer à écrire beaucoup de paquets udp à 8.8.8.8, ces paquets sont abandonnés après 4 sauts, ils ne doivent donc pas atteindre la destination, mais simplement pour simuler le trafic sortant.

Le problème:

Ce code renvoie une erreur OSError (55, ‘No buffer space available’), tandis que sous Linux (Windows aussi), il génère une erreur BlockingIOError, ce qui est correct car il s’agit d’un socket non bloquant.

Ainsi, sur Linux et Windows, le socket se comporte correctement sur OSX, il s’agit d’une erreur OSE, ce qui est mauvais.

Mais ce qui est vraiment intéressant, c’est que même si je mets ce socket en mode de blocage, ce code lance toujours une erreur sur OSX. Alors que sur Linux et Windows, cela ne génère aucune erreur, comme prévu, il ne fait que bloquer.

Est-ce un détail d’implémentation des systèmes basés sur BSD? Ou est-ce que je manque certains parameters réseau importants?

[MODIFIER]

J’ai oublié de mentionner que je testais ce comportement dans un réseau gigabit. Et je pense que c’était le problème. Je me suis connecté à un réseau de 100 Mbits et le problème a disparu, même avec 300 Mbits / s, le problème ne s’est pas produit.

Maintenant, je pense que c’est un comportement spécifique à l’OSX lorsqu’il est connecté à des réseaux haut débit.

[EDIT – FINAL] J’ai finalement trouvé la raison:

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

Sur les systèmes BSD sendto ne JAMAIS bloquer, les documents sont erronés. Mélangé avec certains problèmes spécifiques à OSX lorsqu’il est connecté à des réseaux haut débit. Globalement: il suffit de ne pas penser que sendto bloque, ce n’est pas sur BSD. La bonne chose: si vous le savez, vous pouvez en tenir compte.

Je ne pense pas que vous vouliez lier la prise. Cela ne devrait être fait que du côté serveur que vous prévoyez d’écouter. Que se passe-t-il si vous laissez tomber l’appel à lier? par exemple:

 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 

J’ai également pu isoler ce problème OSX comme vous pouvez le voir dans cette question SO correspondante: DatagramChannel non bloquant lève SocketException (“Pas d’espace tampon disponible”) sur OSX mais le paquet UDP est toujours envoyé avec succès

Cela ressemble à un bug.