Utilisation de l'API de socket Unix sur Linux, existe-t-il un moyen de garantir que je lisais un paquet UDP, et un seul paquet UDP? Je lis actuellement des paquets sur une prise non bloquante à l'aide de RECVMSG, avec une taille tampon un peu plus grande que le MTU de notre réseau interne. Cela devrait veiller à ce que je puisse toujours recevoir le paquet complet UDP, mais je ne suis pas sûr de pouvoir vous garantir que je ne recevrai jamais plus d'un paquet par appel RECVMSG, si les paquets sont petits. P>
Les pages RECVMSG Man font référence à l'option msg_waitall, qui tente d'attendre que le tampon soit rempli. Nous n'utilisons pas cela, il en va de même que cela implique que RECVMSG reviendra toujours après que un datagramme soit lu? Y a-t-il un moyen de garantir cela? P>
Idéalement, je voudrais une solution croisée, mais si cela n'existe pas, il y a quelque chose de Linux spécifique? P>
3 Réponses :
de La documentation POSIX : P>
La fonction RECVMSG () doit recevoir un message d'une prise de mode de connexion ou de mode sans connexion. P>
blockQuote>
"Un message" signifie exactement un message (ou un paquet) et, p>
Pour les prises basées sur des messages, telles que SOCK_DGRAM et SOCK_SEQPACKET, l'ensemble du message doit être lu en une seule opération. P>
blockQuote> RECVMSG code> vous retournera un paquet, et ce sera le paquet entier (tant que le tampon que vous fournissez est suffisamment grand). P>
S'il y a une fragmentation. RECEIVESGG CODE> Rendez-vous uniquement après que l'ensemble du paquet est reconstruit?
Artium: Oui, cela est effectué par le système d'exploitation et l'espace d'utilisateur ne verra que des paquets assemblés et non des fragments. Cela signifie qu'un paquet fragmenté reçu sera tenu par le système d'exploitation pendant un certain temps en attendant le reste des fragments.
Une option (ipo-option) est d'utiliser pcap_next en utilisant libpcap et Laissez-le séparer pour voir s'il s'agit d'un paquet UDP. Vous pouvez le faire avec: (emprunté à partir de tcpdump) p> puis testez la structure IP pour voir s'il s'agit d'un paquet UDP en faisant: P> et si cela échoue, gardez la boucle (appelant pcap_next) jusqu'à ce que vous obteniez votre paquet UDP. Bien entendu, l'extraction du datagramme UDP est plus difficile de cette façon, mais cela vous permet de vous laisser entrer dans le paquet interne assez bien. Reportez-vous à la source TCPDump pour savoir comment supprimer l'info et ce qui sort. P> p>
La réponse acceptée ne répond pas clairement à la question de l'OP, car elle mentionne la taille de la mémoire tampon uniquement en passant. P>
Je lis actuellement des paquets d'une prise non bloquante à l'aide de RECVMSG, avec une taille tampon un peu plus grande que le MTU de notre interne réseau. p> blockQuote>
Il est important que votre tampon soit assez gros pour s'adapter à un datagramme entier. Un datagramme peut atteindre 65 536 octets. Lorsqu'un grand datagramme est fragmenté à cause de MTU, il sera réassemblé par la pile, vous ne le saurez pas à ce sujet, vous ne recevrez rien jusqu'à ce que tous les fragments ne soient reçus et remis ensemble dans le datagramme d'origine. Si vous faites votre tampon légèrement plus gros qu'un MTU, par exemple 1600 octets, et que vous appelez RECV () sur un datagramme entrant de 40 000 octets, vous obtiendrez simplement les 1600 premiers octets. p>
Msg_waitall est pour les sockets orientées par le flux: Linux.die.net/man/3/RecVMSG Comme déjà répondu, RECV / ENVOYER () Travailler à l'aide de datagrammes entiers pour les prises orientées Datagramme.