Pourquoi un socket lit-il plus de données que ce qui est réellement envoyé?

J’ai un client et un serveur écrits en C et fonctionnant sous Linux. Le client demande des segments de données et envoie des segments de données similaires au serveur. Voici les interactions typiques entre le client et le serveur.

  1. Les clients demandent au serveur de sauvegarder certaines données (demande d’écriture). La demande est composée de 4 Ko de données et de quelques octets supplémentaires de métadonnées (2x non signé long + 1xint). Le serveur enregistre les données et ne répond pas aux demandes d’écriture.
  2. Les clients demandent des données au serveur (demande de lecture). La requête est composée de quelques octets de métadonnées (encore une fois … 2xunigned long + 1xint). Le serveur répond avec un segment de données de 4 Ko uniquement.

La trace côté serveur indique qu’il envoie toujours des segments de données de 4 Ko. Cependant, la trace chez les clients montre une histoire différente: des paquets de tailles différentes. Si, à un moment donné, le client reçoit des données d’une taille autre que 4 Ko, le paquet suivant s’ajoute à 4 Ko ou 8 Ko.

Pour illustrer le motif défectueux, voici quelques exemples que j’ai vus dans la trace:

  • 4 Ko, 1200 octets, 2896 octets, 4 Ko.
  • 4 Ko, 1448 octets, 6744 octets, 4 Ko.

Je peux probablement traiter le premier scénario (1200B + 2896B) au niveau de l’application en attendant la lecture d’un segment complet de 4 Ko, mais je ne sais pas comment gérer l’autre. Cependant, je préférerais éviter tout le problème et forcer le client / serveur à recevoir des segments de données complets de 4 Ko chacun.

J’ai déjà essayé de désactiver l’algorithme Nagle ( TCP_NODELAY ) et de définir la taille de la MTU sur 4 Ko. Mais ni l’un ni l’autre n’a résolu le problème.

Pourquoi un socket lit-il plus de données que ce qui est réellement envoyé?

Ce n’est pas. Il lit toutes les données disponibles, après avoir bloqué si nécessaire, alors qu’il n’y en a pas.

Votre question est fondée sur une erreur. Rien dans la spécification du protocole TCP ou l’API Berkeley Sockets n’est garanti qu’une lecture = = une écriture. TCP est un protocole de stream d’octets. Si vous recevez plus de données que prévu et qu’il y a suffisamment de place dans la mémoire tampon que vous fournissez à la méthode recv () ou read (), vous l’obtiendrez. Si vous souhaitez définir les limites des messages, il vous appartient de les implémenter.