45 votes

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

Est-ce que les paquets TCP peuvent arriver au récepteur 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 quelque chose du genre?

Et la même question pour le protocole UDP.
Je sais que l'UDP est peu fiable et que les paquets peuvent ne 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, et non un morceau?

37voto

David Schwartz Points 31009

Les paquets TCP peuvent-ils arriver au récepteur morcelés ?

Oui. IP prend en charge la fragmentation, bien que TCP essaie généralement de déterminer la MTU du chemin et de garder ses paquets plus petits que cela pour des raisons de performance. La fragmentation augmente de manière catastrophique le taux de perte de datagrammes. Si un chemin a un taux de perte de paquets de 10 %, le fait de fragmenter un datagramme en deux paquets augmente le taux de perte du datagramme à presque 20 %. (Si l'un des paquets est perdu, le datagramme est perdu.)

Vous n'avez pas à vous en soucier, et le TCP non plus. La couche IP reconstitue les paquets en datagrammes complets.

Par exemple : si j'envoie 20 octets en utilisant le protocole TCP, puis-je être sûr à 100 % que je recevrai exactement 20 octets en une seule fois, et non pas 10 octets, puis encore 10 octets, ou quelque chose comme ça ?

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

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

C'est la même chose pour TCP. Les paquets sont des paquets. La différence est que TCP a des tentatives de réessais et de réorganisation intégrées dans le protocole, alors qu'UDP non.

Mais qu'en est-il d'un paquet unique ? S'il arrive, puis-je être sûr que c'est un paquet complet, et non pas un morceau ?

Non, mais ce n'est pas votre problème. Le protocole UDP gère la reconstitution des datagrammes. C'est une partie de son travail. (En réalité, le protocole IP le fait pour le protocole UDP, donc l'UDP le fait simplement en étant superposé à l'IP.) Si un datagramme est coupé en deux paquets, le protocole IP le reconstituera pour le protocole UDP, de sorte que vous verrez les données complètes.

21voto

replay Points 3140

Vous ne pouvez pas être sûr qu'ils arrivent réellement physiquement en même temps. Les couches de liaison de données sous TCP/UDP peuvent diviser votre paquet en plusieurs parties si elles le souhaitent. Surtout si vous envoyez des données sur Internet ou sur des réseaux étrangers, il est difficile de prédire cela.

Mais peu importe si les données arrivent dans un seul paquet ou plusieurs paquets chez le récepteur. Le système d'exploitation devrait abstraire la concaténation de ces paquets, de sorte que pour votre application, il semble toujours que tout soit arrivé en même temps. Donc, sauf si vous êtes un hacker de noyau, dans la plupart des cas, vous n'avez pas à vous soucier de savoir si ces données sont transférées en un ou plusieurs paquets.

Pour UDP, le système d'exploitation fera également une certaine abstraction, de sorte que 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 par rapport à TCP est qu'il n'y a aucune garantie que les données arriveront effectivement. Il est également possible que les données soient divisées en plusieurs paquets, et que certains arrivent et d'autres non. Pour l'application de réception, cela semble être un flux de données de toute façon, que ce soit complet ou non.

19voto

Jason de Belle Points 71

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

TCP:

Envoyer : AA BBBB CCC DDDDDD E         Recevoir : 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 blocs.

UDP:

Envoyer : AA BBBB CCC DDDDDD E         Recevoir : 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 préservés dans leur intégralité.

6voto

Changaco Points 870

Par exemple : si j'envoie 20 octets en utilisant le protocole TCP, puis-je être sûr à 100% que je vais recevoir exactement 20 octets à la fois, et non pas 10 octets puis 10 autres octets ou quelque chose du genre ?

Non, TCP est un protocole de flux, il garde les données dans l'ordre mais ne les regroupe pas par message. En revanche, UDP est orienté message, mais peu fiable. SCTP a le meilleur des deux mondes mais n'est pas nativement utilisable car les NAT cassent Internet.

1voto

Kaz Points 477

Il existe une certaine assurance que si vous envoyez 20 octets au tout début d'un flux TCP, cela n'arrivera pas en deux morceaux de 10 octets chacun. C'est parce que la pile TCP ne renverra pas de si petits segments : il y a une taille MTU minimale. Cependant, si l'envoi se fait n'importe où dans le milieu d'un flux, tout est possible. Il se peut que votre pile de protocole prenne 10 octets de données pour remplir un segment et l'envoyer, puis que les dix octets suivants aillent dans un autre segment.

Votre pile de protocole divise les données en morceaux et les place dans une file d'attente. Les tailles des morceaux sont basées sur la MTU du chemin. Si vous effectuez une opération d'envoi et qu'il y a encore des données en attente dans la file d'attente, la pile de protocole va généralement jeter un œil au segment qui se trouve à la fin de la file d'attente pour voir s'il y a de la place dans ce segment pour ajouter plus de données. La place peut être aussi petite qu'un octet, donc même un envoi de deux octets peut être divisé en deux.

D'autre part, 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 dès qu'un seul segment arrive. Dans l'API de sockets largement mise en œuvre, un appel de réception peut demander 20 octets, mais il pourrait retourner avec 10. Bien sûr, une couche tampon peut être construite dessus, qui bloquera jusqu'à ce que 20 octets soient reçus, ou que la connexion soit interrompue. Dans le monde POSIX, cette API peut être les flux d'E/S standard : vous pouvez fdopen un descripteur de socket pour obtenir un flux FILE * et vous pouvez utiliser fread dessus pour remplir un tampon de telle sorte que la requête complète soit satisfaite avec autant d'appels read que nécessaire.

Les datagrammes UDP encadrent les données. Chaque appel d'envoi génère un datagramme (mais voir ci-dessous au sujet de corking). L'autre côté reçoit un datagramme complet (et, dans l'API de socket, il doit spécifier un tampon assez grand pour le contenir, sinon le datagramme sera tronqué). Les grands datagrammes sont fragmentés par la fragmentation IP, et sont ré-assemblés de manière transparente pour les applications. Si un fragment manque, 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, un socket peut être "corked" (empêché d'envoyer). Pendant qu'il est "corked", les données écrites sont assemblées en une seule unité. Ensuite, lorsque le socket est "uncorked", un seul datagramme peut être envoyé.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X