Est-il possible de vider une prise POSIX?

Existe-t-il un appel standard pour rincer le côté émission d’un socket POSIX jusqu’à l’extrémité distante ou cela doit-il être implémenté dans le cadre du protocole de niveau utilisateur? J’ai regardé autour des en-têtes habituels mais je n’ai rien trouvé.

Pour les sockets de domaine Unix, vous pouvez utiliser fflush() , mais je pense que vous voulez probablement dire sockets réseau. Il n’y a pas vraiment de concept pour chasser ceux-ci. Les choses les plus proches sont:

  1. À la fin de votre session, appelez shutdown(sock, SHUT_WR) pour fermer les écritures sur le socket.

  2. Sur les sockets TCP, désactivez l’algorithme Nagle avec sockopt TCP_NODELAY , ce qui est généralement une idée terrible qui ne fera pas de manière fiable ce que vous voulez, même s’il semble s’en occuper lors de l’enquête initiale.

Il est très probable que le traitement de tout problème nécessitant un «vidage» au niveau du protocole utilisateur sera la bonne chose.

Qu’en est-il de définir TCP_NODELAY et de le réinitialiser? Cela pourrait probablement être fait juste avant d’envoyer des données importantes, ou lorsque nous aurons fini d’envoyer un message.

 send(sock, "notimportant", ...); send(sock, "notimportant", ...); send(sock, "notimportant", ...); int flag = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); send(sock, "important data or end of the current message", ...); flag = 0; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); 

Comme le dit la page de manuel linux

TCP_NODELAY … définir cette option force le vidage explicite de la sortie en attente …

Donc, il serait probablement préférable de le définir après le message, mais je ne suis pas sûr de savoir comment cela fonctionne sur d’autres systèmes.

À ma connaissance, l’interface de socket TCP / IP standard ne permet pas de vider les données “jusqu’à l’extrémité distante” et de s’assurer qu’elles ont été acquittées.

De manière générale, si votre protocole nécessite un transfert de données “en temps réel”, il est généralement préférable de définir la TCP_NODELAY setsockopt() de TCP_NODELAY . Cela désactive l’algorithme de Nagle dans la stack de protocole et write () ou send () sur le socket mappe plus directement sur les envois sur le réseau …. au lieu de mettre en œuvre des hold holds en attendant que plus d’octets soient disponibles et en utilisant tous les Des temporisateurs de niveau TCP pour décider quand envoyer. REMARQUE: Désactiver Nagle ne désactive pas la fenêtre glissante TCP ni quoi que ce soit, il est donc toujours sécuritaire de le faire …. mais si vous n’avez pas besoin des propriétés “temps réel”, la surcharge des paquets peut augmenter assez rapidement.

Au-delà de cela, si les mécanismes de socket TCP normaux ne conviennent pas à votre application, vous devez généralement utiliser UDP et créer vos propres fonctionnalités de protocole sur les propriétés d’envoi / réception de base d’UDP. Ceci est très courant lorsque votre protocole a des besoins particuliers, mais ne sous-estimez pas la complexité de le faire correctement et de le rendre stable et fonctionnellement correct dans toutes les applications, sauf relativement simples. Comme sharepoint départ, une étude approfondie des caractéristiques de conception de TCP permettra de mieux comprendre nombre des problèmes à prendre en compte.

Dans la RFC 1122, le nom de la chose que vous recherchez est “PUSH”. Bien que je ne connaisse aucune API TCP qui implémente “PUSH”.

Certaines réponses et commentaires traitent de l’algorithme de Nagle. La plupart d’entre eux semblent supposer que l’algorithme de Nagle retarde chaque envoi. Cette hypothèse n’est pas correcte. Nagle retarde l’envoi uniquement lorsqu’un accusé de réception d’un paquet précédent n’a pas encore été accusé ( http://www.unixguide.net/network/socketfaq/2.11.shtml ).

Pour simplifier un peu: TCP essaie d’envoyer immédiatement le premier paquet (d’une rangée de paquets) mais retarde les paquets suivants jusqu’à ce qu’une temporisation soit atteinte ou que le premier paquet soit acquitté – selon la première éventualité.

Une solution consiste à éviter ces “paquets ultérieurs”. Si votre application appelle send () plus d’une fois pour transmettre une requête composée unique, essayez de réécrire votre application. Assemblez la demande dans l’espace utilisateur, puis appelez send() . Une fois que.

En outre, lorsque le tampon d’envoi contient suffisamment de données pour remplir la taille maximale d’un paquet réseau, Nagle ne tarde pas non plus. Cela signifie que Nagle ne retarde pas (vraiment) un envoi en vrac, même si vous send() les données en vrac par petits morceaux.

Je pense que ce serait extrêmement difficile, voire impossible, de mettre en œuvre correctement. Quelle est la signification de “flush” dans ce contexte? Octets transmis au réseau? Octets reconnus par la stack TCP du destinataire? Octets transmis à l’application en mode utilisateur du destinataire? Octets complètement traités par l’application en mode utilisateur?

On dirait que vous devez le faire au niveau de l’application …

Le protocole TCP ne fournit que la livraison au mieux, de sorte que le fait de laisser tous les octets en réserve de la machine A est asynchrone, leur stack ayant tous été reçue sur la machine B. La stack de protocoles TCP / IP est bien sûr connue, mais je ne connais aucune moyen d’interroger la stack TCP pour savoir si tout ce qui a été envoyé a été reconnu.

De loin, le moyen le plus simple de traiter la question est au niveau de l’application . Ouvrez un second socket TCP pour agir en tant que canal de retour et demandez au partenaire distant de vous envoyer un accusé de réception indiquant qu’il a reçu les informations souhaitées. Cela coûtera le double, mais sera complètement portable et vous fera économiser des heures de temps de programmation.

Vous pouvez définir l’option tcp SO_LINGER pour définir un certain délai, puis fermer le socket afin de vous assurer que toutes les données ont été envoyées (ou détecter tout échec) lors de la fermeture d’une connexion. En dehors de cela, TCP est un protocole “au mieux”, et il ne fournit aucune garantie réelle que les données atteignent réellement la destination (contrairement à ce que certains semblent croire), il essaie simplement de le faire au mieux. dans le bon ordre et le plus tôt possible.

Utilisez fsync ():

sock_fd est un descripteur de fichier entier provenant de l’appel de socket (…, …)

fsync (sock_fd);