J'ai un problème dans la compréhension de ce que RECV () / RECVFROM () retour d'une prise non bloquine UDP. P>
Un peu plus spécifique et comparé au TCP (veuillez me corriger si je me trompe): P>
Une prise de blocage (TCP ou UDP) ne reviendra pas d'un RECV () jusqu'à ce qu'il y ait des données dans le tampon. Cela pourrait être un certain nombre d'octets (TCP) ou un datagramme complet (UDP). P> li>
Une prise TCP non bloquante renvoie EwouldBlock (Linux) / WsaewouldBlock (Windows) ou les octets actuellement dans le tampon. En tant que données TCP étant un flux, cela n'a pas d'importance, combien d'octets sont retournés. P> li> ul>
Maintenant la question: p>
EDIT: P>
Ce que je veux dire avec "la moitié d'un datagramme" est: que se passe-t-il si j'appelle RECV () dans le moment où la prise reçoit actuellement un datagramme. À ce moment-là, il y a des octets dans le tampon, mais le datagramme n'est pas encore complet. P>
Vos explications et vos commentaires sont appréciés. Merci! P>
3 Réponses :
Je crois que vous obtenez précisément un ou zéro datagrammes. Mais je ne peux pas remonter ça en ce moment. Peut-être que quelqu'un d'autre pourrait fournir une bonne référence? P>
Edit: Je suis à peu près sûr que vous ne pouvez pas recevoir un demi-datagramme. Soit le datagramme est arrivé dans le tampon dans, ou il n'a pas. P>
Je crois que c'est correct. Vous pouvez également obtenir une erreur si cela ne s'intègre pas dans le tampon que vous avez fourni ou si vos MBUFS ne sont pas assez gros (arrive parfois avec de gros datagrammes fragmentés parfois).
Les MBUFS sont une structure de données du noyau BSD. Ils ne sont pas exposés à Userland.
Oui, UDP revient simplement quelles données ont été transmises dans un datagramme. UDP n'est pas axé sur le flux comme TCP. Les datagrammes sont des transmissions discrètes et ne sont pas vraiment liées à d'autres datagrammes de quelque manière que ce soit. C'est la raison pour laquelle l'option Socket pour TCP est Sock_Stream. P>
Le côté lumineux de ceci est que vous pouvez avoir une idée des transmissions distinctes, ce qui n'est pas vraiment facile à voir avec TCP. P>
Merci à vous deux. Je connais la différence entre le TCP orienté ruisseau (sock_stream) et l'UDP orienté paquet (SOCK_DGRAM). Je n'étais tout simplement pas sûr de savoir si un RECV UDP non bloqué () serait aussi bien orienté du paquet. Pour citer le MANGAGE RECV (): ... Si aucun message n'est disponible sur la prise, les appels de réception attendent qu'un message arrive, à moins que la prise ne bloque pas (voir FCNTL (2)), auquel cas la valeur -1 est renvoyé et la variable externe errno est définie sur Eagain ou EwouldBlock. Les appels de réception renvoient normalement toutes les données disponibles, B> ...
Enfin, une excuse pour creuser mes livres de Stevens de mes vieilles boîtes de bureau. P>
À condition que le tampon soit suffisamment grand, les standards Berkeley sockets Fait intéressant, ce n'est pas beaucoup (tout?) d'un problème aujourd'hui, d'autres interfaces de programmation de réseau ne sont pas d'accord sur le comportement lorsque le tampon fourni est trop petit: P>
La version traditionnelle de Berkeley de la API de sockets tronque le datagramme, en écartant des données excédentaires. Si l'application est notifiée dépend de la version. (4.3bsd Reno et ultérieurement peuvent notifier à l'application que le datagramme a été tronqué.) P>
Les sockets API sous SVR4 (y compris Solaris 2.x) ne tronque pas le datagramme. Toute données en excès est renvoyée dans des lectures ultérieures. L'application n'est pas notifiée que plusieurs lectures sont remplies d'un seul datagramme UDP. P>
L'API TLI ne jette pas les données. Au lieu de cela, un drapeau est renvoyé indiquant que plus de données sont disponibles et que les lectures ultérieures par l'application renvoient le reste du datagramme. P>
blockQuote>
(Stevens, TCP / IP illustré, volume 1, p. 160) p> RECV () CODE> et RECVFROM () CODE> Les fonctions ne renvoient jamais de datagramme partiel. Le datagramme n'est pas disponible pour l'application tant que le noyau ait complètement reçu et réassemblé le datagramme. P>
Il semble qu'il est possible de passer et de recevoir un drapeau msg_trunc sur RECVMSG code> sous Linux. Documenté dans le MANPAGE RECV (2) CODE>. Sur une autre note, peut-être que je suis mal interprétée, mais je ne peux trouver que le comportement de mise au rebut documenté dans le manuel de la prise (2) code>, qui ne le mentionne que pour sock_seqpacket code> sockets. Je n'ai jamais utilisé ceux personnellement.
msg_trunc code> comme argument sur RECV (2) code> n'est pas standard. Ce n'est pas disponible sur FreeBSD ou Mac OS X (les systèmes dont j'ai accès pour le moment; probablement vrai pour les autres). msg_trunc code> est disponible sur Linux, FreeBSD et Mac OS X dans le membre code> membre code> du fichier struct msghdr code> transmis à recvmsg (2) < / code>. Dans tous les cas, le datagramme sera tronqué si le tampon réussi n'est pas assez grand, même avec RECV (2) code> sur Linux. L'appelant doit vérifier la valeur de retour et la comparer à la taille de la mémoire tampon si msg_trunc code> est utilisé là-bas. Cela saura que les données sont perdues, mais c'est toujours perdu.
Soyez prudent avec votre terminologie. UDP est orienté Datagramme. Les paquets sont la "chose sur le fil" et à tout moment que vos datagrammes UDP sont plus gros que le MTU, ils seront fragmentés à la couche IP, ce qui entraînera plusieurs paquets IP. Le réassemblage arrive au récepteur avant que tout soit disponible pour la demande.
Oui vous avez raison. Pour résumer: - Si aucune donnée n'est disponible, RECV () renvoie ewouldBlock. - Compte tenu d'un tampon trop petit pour un datagramme complet, le datagramme est tronqué et tout ce qui ne va pas dans le tampon se perd. - Si le tampon est assez important, RECV () renvoie exactement un datagramme.