2017-06-01 6 views
0

Assumer le code suivant (par souci de simplicité, j'ai omis l'erreur nécessaire manipulation ici):Puis-je être sûr qu'un recup UDP exécuté immédiatement après un appel réussi à recv avec MSG_PEEK ne bloquera pas?

recv(sockfd, NULL, 0, MSG_PEEK); 
recv(sockfd, buff, bufflen, 0); 

Dans ce cas: Puis-je être sûr que, après le premier appel à la recv datagrammes tout est déjà reçu et donc le deuxième appel à recv ne bloquera pas?

Ou peut-il arriver que si IP sépare le datagramme, le premier recv retourne dès qu'une partie de ce datagramme est reçue, et le second recv va bloquer jusqu'à ce que le datagramme entier soit reçu?

Si je remplace le premier appel à recv avec:

recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC); 

Puis-je être sûr que cela ne retournera une fois que le datagramme entier est reçu, car il serait par ailleurs aucun moyen pour recv pour revenir de manière fiable la longueur du datagramme entier, comme demandé par MSG_TRUNC?

+1

Pas s'il existe un autre processus ou thread avec FD pour le même socket. Il pourrait lire le paquet avant vous. – Barmar

Répondre

3

Puis-je être sûr que, après le premier appel à recv l'ensemble est datagrammes déjà reçu et donc le deuxième appel à la RECV ne sera pas bloc?

Une socket UDP fonctionne dans des unités de datagramme entier. Le premier appel ne retournera pas tant qu'un datagramme n'est pas disponible, sauf s'il renvoie -1 pour indiquer une erreur. (Un socket TCP peut retourner 0 à la fermeture de la connexion, mais cela ne se produira pas avec un UDP, car il est sans connexion.)

@Barmar observe dans les commentaires qu'un autre thread ou processus ayant accès à la même socket peut, en principe, lire ce datagramme en attente avant celui qui a appelé le premier recv(), mais si ce n'est pas un souci pour vous alors le prochain recv() devrait renvoyer le datagramme entier, jusqu'à la quantité d'espace disponible dans le tampon (tout excès d'octets dans le message est perdu). Bien sûr, cela soulève la question de savoir pourquoi vous voulez faire cela - vous auriez tout aussi bien pu sauter le premier recv(), et laisser le second bloquer si nécessaire. L'ajout de MSG_TRUNC aux drapeaux ne modifie aucun des éléments ci-dessus. Encore une fois, une socket UDP fonctionne dans des unités de datagramme entier. La seule différence est que la valeur de retour vous donne la taille du datagramme. Cette peut être une raison pour l'appel supplémentaire recv().

+0

Pourquoi une telle construction? J'ai deux threads, l'un répétant à plusieurs reprises seulement et l'autre à plusieurs reprises seulement 'send', dans le seul but de les laisser faire leur travail sans avoir à attendre que l'appel de l'autre socket de blocage ne revienne. Par souci de simplicité, je voulais faire la seconde 'recv' sous un mutex protégeant les données communes verrouillées, afin que cette seconde' recv' puisse écrire sur cette donnée commune. Si cette seconde 'recv' ne bloque pas, ça va. Si cela pouvait bloquer, alors l'idée n'aurait pas beaucoup de sens. – gaazkam