Fragmentation TCP / UDP et Ethernet MTU

J’ai lu divers sites et tutoriels en ligne, mais je suis toujours confus. Si le message est plus grand que le MTU IP, alors send() renvoie l’octet envoyé. Qu’advient-il du rest du message? Dois-je appeler à nouveau send() et tenter d’envoyer le rest du message? Ou est-ce quelque chose que la couche IP devrait régler automatiquement?

Si vous utilisez TCP, l’interface qui vous est présentée est celle d’un stream d’octets. Vous n’avez pas à vous soucier de la façon dont le stream d’octets passe d’une extrémité de la connexion à l’autre. Vous pouvez ignorer le MTU de la couche IP. En fait, vous pouvez ignorer complètement la couche IP.

Lorsque vous appelez send() la stack TCP de votre ordinateur traitera de tous les détails nécessaires au stream d’octets que vous poussez dans vos appels d’envoi afin qu’ils apparaissent à partir d’appels recv() situés à l’autre bout de la connexion.

Une chose à garder à l’esprit est qu’avec TCP, vous traitez avec un stream, ce qui signifie qu’un send() peut avoir comme conséquence que les données arrivent dans plusieurs appels recv() et que plusieurs appels send() peuvent aboutir à des données qui arrivent dans un seul recv() appeler. Vous n’avez aucun contrôle sur cela. Vous traitez avec un stream d’octets et chaque appel à recv() peut renvoyer n’importe quel nombre d’octets, de 1 au nombre actuellement en attente (en permettant à des tampons adéquats de passer à l’appel de recv() ).

Depuis les commentateurs l’ont demandé;)

Sur la plupart des stacks TCP, send() échouera probablement à tout envoyer parce que les tampons de la stack TCP sont pleins et que (probablement) la fenêtre TCP est également pleine et que le contrôle de stream fonctionne, ce qui signifie que la stack ne peut plus envoyer de données. jusqu’à ce que l’exécutif distant accuse des données et qu’il n’est plus prêt à mettre en mémoire tampon vos données personnelles. Je n’ai pas rencontré de stack TCP qui refuse un send() uniquement pour des raisons de MTU, mais je suppose que certains systèmes embarqués allégés pourraient se comporter de cette façon …

Quoi qu’il en soit, si send() renvoie moins que le nombre d’octets que vous avez fourni, vous devriez alors renvoyer les données restantes à un moment donné. Souvent send() bloquera et attendra jusqu’à ce qu’il puisse envoyer toutes les données, et si vous avez configuré le socket en mode non bloquant, vous ne voudrez probablement PAS retenter immédiatement l’envoi s’il ne parvient pas à tout envoyer comme vous le feriez probablement se retrouver dans une boucle serrée …

Il serait probablement utile que vous soyez plus précis sur le système d’exploitation que vous utilisez.

Si le paquet est trop volumineux pour transiter sur le réseau, une indication de fragmentation ICMP est envoyée pour indiquer à l’expéditeur de réduire la taille du paquet et de réessayer.

Si vous utilisez TCP, ce sont tous des détails auxquels vous devez vous attendre. Ce que les entresockets IP modernes font réellement en coulisse pour comprendre le MTU le plus bas sur le chemin semble être devenu en quelque sorte un art noir.

WRT UDP, vous pouvez toujours vous attendre à ce que la stack se fragmente, mais dans la pratique, étant donné le cas d’utilisation d’UDP, ce n’est pas idéal. Selon votre application, vous obtiendrez probablement de meilleures performances en comprenant explicitement le chemin MTU.

… sur la question send (), certaines stacks se comportent différemment, mais le traitement de votre code doit être identique. Disons que vous avez 100 octets à envoyer … send () renvoie 10 octets envoyés. Vous devez continuer à appeler en envoyant avec les 90 octets restants jusqu’à ce que tout soit mis hors service pour envoyer le message en entier.

En utilisant des sockets de blocage sur la plate-forme Windows send () retournera généralement après que tout soit envoyé .. Sur d’autres plates-formes .. Linux et al vous aurez besoin de continuer à envoyer plus souvent pour envoyer les données.