Prise C: envoie-t-on attendre que recv se termine?

J’utilise le blocage des sockets C sous Windows. Je les utilise pour envoyer les mises à jour des données du serveur au client et inversement. J’envoie des mises à jour à haute fréquence (toutes les 100ms). Est-ce que la fonction send() attendra que le destinataire recv() reçoive les données avant de se terminer?

Je suppose que non si je comprends bien la page de manuel:

“La réussite de send () ne garantit pas la livraison du message.”

Alors que se passera-t-il si on exécute 10 occurrences send() alors que l’autre n’a que 1 recv() complet?

Dois-je utiliser une sorte de système de reconnaissance?

Supposons que vous utilisez TCP. Lorsque vous appelez send, les données que vous envoyez sont immédiatement placées dans la queue sortante et l’envoi se termine avec succès. Si toutefois, send ne parvient pas à placer les données dans la queue sortante, send retournera avec une erreur.

Tcp étant un protocole de livraison garanti, les données de la queue sortante ne peuvent être supprimées qu’une fois l’accusé de réception reçu par l’extrémité distante. En effet, il peut être nécessaire de renvoyer les données si aucun accusé de réception n’a été reçu à temps.

Si l’extrémité distante est lente, la queue sortante se remplira de données et l’envoi sera ensuite bloqué jusqu’à ce qu’il y ait de la place pour placer les nouvelles données dans la queue sortante.

La connexion peut toutefois échouer de manière à empêcher l’envoi de données supplémentaires. Bien qu’une fois qu’une connexion TCP a été fermée, tout envoi ultérieur entraînera une erreur, l’utilisateur n’a aucun moyen de savoir combien de données ont effectivement été transférées de l’autre côté. (Je ne connais aucun moyen de récupérer la comptabilité TCP d’un socket vers l’application utilisateur). Par conséquent, si une confirmation de la réception des données est requirejse, vous devriez probablement l’implémenter au niveau de l’application.

Pour UDP, je pense qu’il va sans dire qu’un moyen de signaler ce qui a été reçu ou non est indispensable.

send() bloque jusqu’à ce que le système d’exploitation (kernel) prenne les données et les mette dans un tampon de données sortantes. Il n’attend pas que l’autre extrémité ait reçu les données.

Si vous envoyez par TCP, vous obtenez une livraison garantie 1 et l’autre extrémité recevra les données dans l’ordre envoyé. Cela pourrait, cependant, être fusionné afin que ce que vous envoyiez sous forme de 10 mises à jour distinctes puisse être reçu sous la forme d’un seul grand paquet (ou inversement – une seule mise à jour peut être fractionnée en un nombre arbitraire de paquets). Cela signifie, entre autres choses, que tout accusé de réception de n’importe quelle donnée accuse implicitement la réception de toutes les données précédentes.

Si vous utilisez UDP, rien de tout cela n’est vrai: les données peuvent arriver dans le désordre, ou être supprimées et jamais livrées. Si vous vous souciez de toutes les données reçues, vous avez juste besoin de construire votre propre système de reconnaissance par-dessus l’UDP lui-même.

1 Bien entendu, la garantie est limitée: si un câble réseau est coupé (ou peu importe), les paquets ne seront pas livrés, mais vous obtiendrez au moins un message d’erreur vous indiquant que la connexion a été perdue.

Si vous utilisez TCP, vous recevez les accusés de réception gratuitement car cela fait partie de ce que le protocole fait sous le capot. Mais cela ressemble à ce type d’application que vous voudriez probablement utiliser UDP. Dans les deux cas, send() ne bloquera pas tant que le client n’aura pas recv() .

S’il est crucial que le client reçoive chaque message, utilisez TCP. S’il est normal que le client manque un ou plusieurs messages, utilisez UDP.

TCP garantit la livraison à un niveau de stack TCP inférieur. Il tente à nouveau la livraison jusqu’à ce que le destinataire reconnaisse que les données ont été reçues, mais votre application risque de ne jamais être au courant de ce fait.

Supposons que vous envoyez des morceaux de données et que vous devez les placer quelque part selon une logique quelconque. Si votre application n’est pas prête à savoir où chaque bloc doit être placé, il peut s’avérer inutile de le recevoir au niveau TCP. Le message original portait sur la logique au niveau de l’application.