Question Les paquets TCP et UDP peuvent-ils être divisés en morceaux?


Les paquets TCP peuvent-ils arriver au destinataire par morceaux?

Par exemple, si j’envoie 20 octets en utilisant le protocole TCP, puis-je être sûr à 100% que je recevrai exactement 20 octets à la fois, et non 10 octets, puis 10 autres octets ou plus?

Et la même question pour le protocole UDP.
Je sais que UDP n'est pas fiable et que les paquets ne peuvent pas arriver du tout ou arriver dans un ordre différent, mais qu'en est-il d'un seul paquet? S'il arrive, puis-je être sûr que c'est un paquet complet, pas un morceau?


37
2017-08-27 10:02


origine


Une précision: cela s'appelle un segment TCP et un datagramme UDP. Ce ne sont pas des paquets. TCP = Segment, UDP = Datagram, IP = Paquet, Ethernet = Frame, Toutes les autres couches (AFAIK) sont simplement appelées PDU (unités de données de protocole). - joeqwerty


Réponses:


les paquets TCP peuvent-ils arriver au destinataire par morceaux?

Oui. IP prend en charge la fragmentation, bien que TCP tente généralement de déterminer le MTU du chemin et de garder ses paquets plus petits que cela pour des raisons de performances. La fragmentation augmente le taux de perte de datagramme de façon catastrophique. Si un chemin a un taux de perte de paquets de 10%, la fragmentation d'un datagramme en deux paquets fait en sorte que le taux de perte de datagramme est proche de 20%. (Si l'un des paquets est perdu, le datagramme est perdu.)

Cependant, vous n'avez pas à vous soucier de cela, pas plus que la couche TCP. La couche IP rassemble les paquets en datagrammes entiers.

Exemple: si j'envoie 20 octets en utilisant le protocole TCP, puis-je être sûr à 100% que je recevrai exactement 20 octets à la fois, et non 10 octets, puis 10 autres octets ou plus?

Non, mais cela n'a rien à voir avec les paquets. Le protocole TCP est fondamentalement un protocole de flux d'octets qui ne préserve pas les limites des messages d'application.

Et la même question pour le protocole UDP. Je sais qu’UDP n’est pas fiable et que les paquets ne peuvent pas arriver du tout ou arriver dans un ordre différent,

La même chose est vraie pour TCP. Les paquets sont des paquets. La différence est que TCP a des tentatives et des réordonnances intégrées au protocole, contrairement à UDP.

mais qu'en est-il 1 paquet? S'il arrive, puis-je être sûr que c'est un paquet complet, pas un morceau?

Non, mais ce n'est pas ton problème. Le protocole UDP gère le réassemblage du datagramme. Cela fait partie de son travail. (En réalité, le protocole IP le fait pour le protocole UDP. UDP le fait simplement en se superposant au-dessus d'IP.) Si un datagramme est divisé en deux paquets, le protocole IP le réassemblera pour le protocole UDP. verra les données complètes.


29
2017-08-27 10:27



Cela vaut peut-être la peine de préciser le dernier point pour les lecteurs novices: vous verrez les données complètes  pour le datagramme en question. Si l'un des paquets divisés est perdu, le datagramme est perdu et la couche UDP ne le saura jamais. Tant que tous les paquets du datagramme sont reçus, ils seront assemblés au niveau de la couche IP puis transmis à la couche UDP. Cela n'exclut pas la possibilité de manquer des "morceaux" dans le flux de données. Ne pas être un pédant, mais quand j'ai appris ce truc, je n'ai pas expliqué la différence entre une perte d'IP et une perte d'UDP avant la deuxième ou la troisième traversée du manuel. - Justin ᚅᚔᚈᚄᚒᚔ


Vous ne pouvez pas être sûr qu'ils arrivent vraiment physiquement à la fois. Les couches de liaison de données sous TCP / UDP peuvent scinder votre paquet si elles le souhaitent. Surtout si vous envoyez des données via Internet ou des réseaux indépendants de votre volonté, il est difficile de prédire cela.

Mais peu importe si les données arrivent en un ou plusieurs paquets chez le destinataire. Le système d'exploitation doit extraire la concaténation de ces paquets. Par conséquent, pour votre application, tout se passe comme si tout était arrivé en même temps. Ainsi, à moins que vous ne soyez un pirate du noyau, dans la plupart des cas, vous n'avez pas à vous inquiéter si ces données sont transférées dans un ou plusieurs paquets.

Pour UDP, le système d'exploitation effectue également des abstractions. Ainsi, l'application qui reçoit les données n'a pas besoin de savoir dans combien de paquets les données ont été transmises. Mais la différence avec TCP est qu’il n’ya aucune garantie que les données arrivent réellement. Il est également possible que les données soient divisées en plusieurs paquets. Certains arrivent, d'autres non. Pour l’application réceptrice, cela ressemble quand même à un flux de données, qu’elles soient complètes ou non.


19
2017-08-27 10:04



Le pilote de la carte réseau ne s'occupe-t-il pas de réassembler les paquets, pas le noyau? - bluehallu
@Hallucynogenyc: À moins que les choses ne changent, le protocole Internet est conçu pour permettre aux paquets de plus de 576 octets d'être fractionnés à tout moment de leur voyage, mais n'attend que le destinataire final pour les recombiner. Je pense que l’idée est que l’utilisation de paquets plus gros était dans la plupart des cas un effort pour réduire les frais généraux; une fois qu'un paquet a été scindé à un moment donné de son parcours, les frais généraux ont déjà été engagés; la recombinaison avant le destinataire final n'aide à rien, et peut faire mal si elle doit être scindée à nouveau. - supercat
Je crois que même si un paquet de plus de 576 octets peut être fractionné, les paquets dont la taille est inférieure à cette taille ne le peuvent pas; Les systèmes embarqués qui ne peuvent pas traiter les paquets divisés doivent éviter de demander plus gros que cela. - supercat
@ mauro.stettler: J'ai écrit une pile TCP sur du "métal nu" (écrire le code pour parler directement à un certain nombre de puces d'interface réseau). Pour le matériel qui communique avec un lien avec une limite de 576 octets pour diviser des paquets plus longs, la procédure est simple. Le réassemblage des paquets est beaucoup plus compliqué, d’autant plus que l’on peut recevoir des morceaux de nombreux paquets différents avant qu’un d’eux ne soit reçu intégralement. - supercat
Il y a un espoir qu'il ne sera pas divisé pour minuscule des charges utiles (environ 10 ou 20 octets devraient suffire), car une "taille maximale garantie" est requise pour chaque saut pour les paquets IP sur ipv4: au moins 68 octets (y compris les en-têtes IP et les en-têtes de niveau inférieur). voir la 1ère table dans en.wikipedia.org/wiki/Maximum_transmission_unit. Différent des 576 octets de taille minimale requis de HOSTS (c'est-à-dire l'origine ou la fin de la transmission, pas tous les sauts intermédiaires). Et attention: le charge utile est plus bas encore (car les en-têtes de chaque couche prennent de la place). - Olivier Dulac


Exemples. Les blocs de caractères contigus correspondent aux appels send ():

TCP:

Send: AA BBBB CCC DDDDDD E         Recv: A ABB B BCC CDDD DDDE

Toutes les données envoyées sont reçues dans l’ordre, mais pas nécessairement dans les mêmes morceaux.

UDP:

Send: AA BBBB CCC DDDDDD E         Recv: CCC AA E

Les données ne sont pas nécessairement dans le même ordre et ne sont pas nécessairement reçues du tout, mais les messages sont conservés dans leur intégralité.


14
2017-08-27 16:22





Exemple: si j'envoie 20 octets en utilisant le protocole TCP, puis-je être sûr à 100% que je   recevra exactement 20 octets à la fois, pas 10 octets, puis 10 autres   octets ou si?

Non, TCP est un protocole de flux, il garde les données en ordre mais ne les groupe pas par message. D'autre part, UDP est orienté message, mais peu fiable. SCTP a le meilleur des deux mondes mais n'est pas utilisable en mode natif, car les NAT brisent Internet.


5
2017-08-27 10:19





Il existe une certaine assurance que si vous envoyez 20 octets au tout début d'un flux TCP, celui-ci n'arrivera pas sous forme de deux morceaux de 10 octets. En effet, la pile TCP n'enverra pas de tels segments: il existe une taille minimale de MTU. Cependant, si l'envoi est n'importe où au milieu d'un flux, tous les paris sont désactivés. Il se peut que votre pile de protocoles utilise 10 octets de données pour remplir un segment et l'envoyer, puis que les dix octets suivants passent à un autre segment.

Votre pile de protocoles divise les données en fragments et les place dans une file d'attente. Les tailles de bloc sont basées sur le MTU du chemin. Si vous effectuez une opération d'envoi et que des données sont toujours en attente, la pile de protocoles examine généralement le segment situé à la fin de la file d'attente et voit s'il y a de la place dans ce segment pour ajouter des données. La pièce peut être aussi petite qu'un octet, de sorte que même un envoi sur deux octets peut être divisé en deux.

Par ailleurs, la segmentation des données signifie qu'il peut y avoir des lectures partielles. Une opération de réception peut potentiellement se réveiller et obtenir des données quand un segment seulement arrive. Dans l’API de sockets largement implémentée, un appel reçu peut demander 20 octets, mais il peut en renvoyer 10. Bien entendu, une couche de mise en mémoire tampon peut être construite sur celle-ci, qui bloque jusqu’à ce que 20 octets soient reçus ou que la connexion soit interrompue. Dans le monde POSIX, cette API peut être le flux d’E / S standard: vous pouvez fdopen un descripteur de socket pour obtenir un FILE * flux, et vous pouvez utiliser fread sur elle pour remplir un tampon de sorte que la demande complète est satisfaite avec autant de read appelle comme il faut.

Les datagrammes UDP encadrent les données. Chaque appel d’envoi génère un datagramme (mais voir ci-dessous à propos du bouchage). L'autre côté reçoit un datagramme complet (et, dans l'API de socket, il doit spécifier un tampon suffisamment grand pour le contenir, sinon le datagramme sera tronqué). Les gros datagrammes sont fragmentés par fragmentation IP et sont réassemblés de manière transparente pour les applications. Si un fragment est manquant, le datagramme entier est perdu; il n'y a aucun moyen de lire des données partielles dans cette situation.

Il existe des extensions à l'interface permettant à plusieurs opérations de spécifier un seul datagramme. Sous Linux, une socket peut être "bouchée" (envoi interdit). Bien qu’il soit bouché, les données écrites sont assemblées en une seule unité. Ensuite, lorsque le socket est "débouché", un seul datagramme peut être envoyé.


1
2017-08-27 16:56



C'est faux: si on envoie un paquet avec une charge utile de 10 ou 20 octets, cela générera 1 paquet, et (comme je l'ai dit plus haut), si vous utilisez ipv4, il devrait, même en ajoutant tous les en-têtes des autres couches de protocole, dans les 68 octets, assurant ainsi qu’il passe par tous les sauts en 1 paquet. La pile TCP ne sera pas (comme indiqué dans votre premier paragraphe) "attendez que le MTU soit rempli (c.-à-d. Ajoutez plusieurs paquets pour en faire un correctement dimensionné)" pour envoyer un paquet! ... Ce comportement casserait beaucoup de choses ( même si ces "fragments" ont été envoyés de & à la même paire d’hôtes) - Olivier Dulac
@ OlivierDulac: C'est inexact. TCP génère généralement les paquets dont il a besoin, en essayant d'optimiser l'utilisation du réseau. Ainsi, 20 octets pourraient se retrouver dans deux paquets différents, comme expliqué par Kaz. Ceci peut être contrôlé en utilisant le TCP_NODELAY L'option socket, qui désactive l'algorithme Nagles qui distribue des octets en paquets, si votre application nécessite un réseau TCP plus rapide. En outre, 68 octets n'est en aucun cas le standard de facto pour la longueur de paquet: 1500 octets est une valeur par défaut plus habituelle (cela varie vraiment entre les réseaux). - jjmontes