• 30 heures
  • Facile

Mis à jour le 24/04/2020

Les protocoles de la couche transport

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Vous savez d’ores et déjà en quoi consiste la couche Transport, étant donné que nous l’avons, non seulement survolée, mais nous avons également analysé les différents services qu’elle nous offre. Dans ce chapitre, nous allons nous focaliser sur les deux protocoles principaux de cette couche, a savoir TCP (Transmission Control Protocol) et UDP (User Datagram Protocol). Nous commencerons par étudier UDP, ensuite nous attirerons votre attention sur TCP. Finalement, nous comparerons les deux protocoles afin de déterminer quand faut-il privilégier l’un au détriment de l’autre. TCP, étant un protocole richissime, nous allons nous plonger dans des détails minutieux dans les chapitres qui suivront.

UDP, un protocole irresponsable

Comme nous l'avons maintes fois répété, UDP est l'un des protocoles les plus utilisés au niveau de la couche transport, juste après TCP. Les deux sont des protocoles dont la vocation est de transporter les données d'une application à une autre comme nous l'avons vu. Dans cette sous-partie, nous allons nous concentrer sur UDP.

UDP par l'analogie

Pour bien aborder une notion importante, une analogie (vous commencez à être habitués :-° ).
Supposons que vous voulez organiser une petite fête chez un ami, Pierre. Votre ami vous a donné la permission d'inviter vos amis, même s'il ne les connait pas. Vos amis, ne connaissant pas Pierre, ne savent pas comment arriver chez lui. Vous leur avez demandé de vous rejoindre chez vous à 17h, afin de vous rendre à la fête ensemble. Le jour J arrive et tous vos amis sont chez vous. Vous décidez alors d'emprunter des taxis pour aller chez Pierre. En sortant de chez vous, il y a une file de plusieurs taxis disponibles. Vous allez donc vous séparer en plusieurs groupes. Chaque groupe prendra son propre taxi. Le but est le même pour tous : arriver chez Pierre. Mais il est fort probable que d'autres arrivent plus tôt que les autres (à cause de feux de circulation, ...). Il est aussi probable que les taxis n'empruntent pas la même route pour arriver à la destination finale. Pour les malchanceux, il se peut même qu'ils aient un accident en route, les empêchant ainsi d'arriver à destination. Ainsi, les taxis ne peuvent pas garantir que tout le monde arrivera à temps, dans les délais voulus, et surtout que tous vont emprunter le même chemin ou arriver au même moment.
(Ça peut paraître difficile à imaginer que plusieurs taxis allant d'un point A à un point B ne se suivent pas les uns les autres. Mais faîtes comme si c'était normal. :-° )

Un autre exemple ?

On décrit souvent UDP comme étant un protocole fire and forget, ce qui signifie en français tire et oublie. Imaginez que vous entendiez un bruit dans la cour de votre villa. Vous allez dans la cour, mais il fait sombre. Vous remarquez quelques mouvements, et vous prenez votre arme et tirez. Vous supposez que ce bandit qui essaie de vous cambrioler est mort et vous rentrez vous recoucher. Vous avez appuyé sur la gâchette et vous êtes rentré sans vous soucier de quoi que que ce soit. Est-ce que la balle a atteint la cible ? Ce n'est pas votre problème. Vous avez tiré et après, si la cible est touchée tant mieux, sinon tant pis.

UDP signifie User Datagram Protocol (protocole d'utilisateur de datagramme). C'est un protocole de transport qui ne peut pas garantir que les données arriveront toutes à destination. C'est d'ailleurs l'un des principaux défauts de ce protocole. On ne peut pas être sûr que les données arriveront au destinataire car UDP n'a pas de mécanisme de retransmission quand un paquet se perd et il est un protocole non orienté connexion.

Dans notre premier exemple, lorsque le taxi a un accident, est-ce qu'il peut soigner ses passagers et ensuite continuer la course vers la destination ? Non ! Donc les passagers n'arriveront pas à destination, en d'autres termes, ils ne seront pas retransmis, donc se perdent. Voilà une petite introduction à ce protocole.

Pourquoi « non orienté connexion » ?

Nous avons vu que dans la couche transport, le mode d'envoi était choisi : mode orienté connexion et non orienté connexion. Pour comprendre le principe de ces deux modes, il nous faut aborder la notion de la poignée de main (handshake).

Le principe de la poignée de main

Image utilisateur

L'image ci-dessus appartient au domaine public.

Pourquoi vous faites cette tête-là ? Ça vous étonne qu'on parle de poignée de main en réseau ? :p Nous ne le dirons jamais assez, la technologie s'inspire du monde réel. ;)

Qu'est-ce qu'une poignée de main ?

Non, c'est pour de vrai, la question est sérieuse. :-°
Une poignée de main est une action qui se fait en deux mouvements : on tend la main et l'autre personne la prend (elle aussi nous tend la main). On se sert de ce rituel dans plusieurs domaines. Par exemple dans la vie quotidienne, la poignée de main est utilisée lors d'une salutation, alors qu'en business, c'est pour signifier une entente, un contrat conclu.

Et en réseau ?

En réseau, on se sert du principe de la poignée de main pour l'initialisation d'une connexion.

Vous vous souvenez du tout premier chapitre sur les protocoles ? Nous avons vu, par l'exemple d'une conversion au téléphone, comment opéraient les protocoles. La première étape d'une communication était l'établissement de la connexion, n'est-ce pas ?
En effet, lorsque vous téléphonez à un ami, il décroche en disant « Allô » et vous répondez « Allô ». C'est le même principe que la poignée de main, vous vous êtes mis d'accord sur le fait que vous allez engager une conversation.

En réseau, le principe reste fondamentalement le même. Quand vous voulez communiquer avec un autre hôte dans un réseau, il faut que les deux hôtes se mettent d'accord. Cette entente se fait par la poignée de main. En fait, l'hôte émetteur envoie un paquet qui dit « Est-ce qu'on peut parler ? » et l'hôte récepteur répond « Vas-y, j'écoute ». Et là les deux peuvent s'échanger des données ! ;)

Le rapport avec UDP ?

Justement, UDP n'est pas orienté connexion du fait qu'il n'implémente pas ce principe de la poignée de main. En d'autres termes, lorsqu'une application utilise UDP comme protocole, les données sont envoyées sans au préalable établir une session ou une connexion avec l'hôte récepteur. C'est pour cela que UDP ne garantit pas que les données vont arriver.

Quand vous utilisez UDP, c'est comme si vous parliez à quelqu'un qu'il soit éveillé ou endormi. S'il est éveillé tant mieux, il vous écoute, il reçoit votre message. Par contre si il dort, bah tant pis, vous aurez beau parler, il ne recevra rien. Voilà pourquoi UDP est un protocole dit orienté transaction, en d'autres termes, il se contente d'envoyer le message et d'espérer que tout se passe bien.

La structure d'un segment UDP

UDP a été créé par David Reed en 1980 et est spécifié par la RFC 768. Comme tout protocole, il a un en-tête qui lui est propre. Dans le chapitre précédent, nous vous avons schématisé quelques champs d'un segment de protocole de transport. Ces champs sont en fait communs à UDP et TCP. Maintenant nous allons voir de quoi est constitué un segment UDP entier. Pour rappel, voici à quoi ressemble un segment de protocole de transport :

Image utilisateur

Les champs présents dans l'image résultent de la fonction de multiplexage et démultiplexage comme nous l'avons vu. Mais UDP ajoute deux champs de plus. Voici la structure d'un segment UDP :

Image utilisateur

Nous n'allons pas revenir sur les champs « Source Port » et « Destination Port », nous y avons déjà passé un bout de temps. Cependant, les deux autres champs « Lenght » (longueur) et « Checksum » (somme de contrôle) vous sont inconnus. Chacun des champs de l'en-tête UDP vaut 2 octets, soit 16 bits chacun. ;)

  • Lenght : ce champ spécifie la longueur de tout le datagramme. Un datagramme est le nom que l'on donne à un PDU envoyé par un protocole non fiable, comme nous l'avons dit dans les chapitres précédents. Étant donné qu'UDP n'est pas fiable, on appelle donc les données à ce niveau « datagramme » (datagram en anglais). Ainsi, le champ « lenght » contiendra la longueur du datagramme. Puisque nous savons déjà que chaque champ de l'en-tête vaut 2 octets, il est donc logique que la valeur minimum de ce champ est de 8 octets (2 octets x 4 champs) soit 64 bits (16 bits x 4 champs).

  • Checksum : aahhh, vous vous souvenez de l'expression somme de contrôle ? La valeur présente dans ce champ indiquera si une erreur s'est produite durant la transmission du datagramme. Nous verrons comment cela fonctionne dans un prochain chapitre.

L'essentiel du protocole UDP

Pour commencer, jetons un coup d'œil aux caractéristiques du protocole UDP :

  • Mode non connecté : nous avons dit que UDP n'utilisait pas un mode orienté connexion, donc il n'implémente pas le principe de connexion par poignée de main

  • État de connexion : l'état de connexion est un sujet un peu complexe pour l'instant, et il est propre à TCP. Alors nous n'allons pas vous faire souffrir pour rien. Retenez juste qu'UDP ne maintient pas des informations sur l'état de la connexion.

  • La longueur de l'en-tête : comme vous avez eu l'occasion de le voir par vous-même, l'en-tête d'un segment UDP est relativement simple. Il ne vaut que 8 octets. Vous allez voir que l'en-tête de TCP est plus complexe que celui d'UDP.

  • Taux de transmission : avec UDP, la vitesse (ou le taux) de transmission est intimement liée aux caractéristiques de l'environnement du système d'exploitation. C'est-à-dire que cette vitesse dépend des ressources système (fréquence du processeur, etc.) d'une part, et de la bande passante d'autre part. Puisque UDP n'a pas de mécanisme de contrôle de congestion (on en a un peu parlé précédemment), le taux de transmission dépend de la vitesse à laquelle l'application utilisée génère ces datagrammes.

Ces caractéristiques révèlent en quelque sorte les avantages d'UDP. Puisqu'il n'est pas orienté connexion, il ne crée donc pas des délais d'attente pour établir une connexion avant transmission. Grossièrement, imaginez qu'envoyer un message « salut » à un hôte prend 3 secondes. Avec TCP, ça prendra 3 secondes + x secondes, x étant le temps mis pour établir une connexion avant la transmission. C'est un exemple très simplifié. ;) Étant donné qu'il ne gère ni l'état de la connexion, ni le contrôle de congestion, il est donc un peu plus rapide que TCP.

Utilisez UDP lorsque vous n'avez pas besoin de garantir que les données envoyées arriveront à leurs destinataires. Par exemple, dans le cadre de la VoIP (la téléphonie via Internet), plusieurs applications utilisent UDP, comme Skype. S'il faut renvoyer les messages vocaux à chaque fois jusqu'à ce qu'ils arrivent, cela va significativement alourdir le réseau, voilà pourquoi les conversations téléphoniques sur Internet se font via UDP. Le service DNS (qui permet de traduire les adresses IP en noms de domaine) utilise également UDP.

Nous allons comparer UDP et TCP plus tard, et c'est là que nous allons voir quand il faut utiliser TCP et quand il fait privilégier UDP.

UDP n'étant pas vraiment un protocole très fondamental de la suite TCP-IP, nous n'allons pas nous attarder sur son compte. En revanche, nous allons vraiment nous attarder sur TCP qui a le mérite de retrouver son nom dans le nom même du modèle de communication sur lequel se base Internet, à savoir TCP-IP. ;)

Le protocole pessimiste : TCP

Nous espérons que vous avez encore en mémoire les exemples précédents (transmission des lettres entre cousins des deux maisons, aller a une fête en groupe en empruntant des taxis…). Dans ces deux exemples, nous avons illustré les principes fondamentaux qui sont aussi les divergences principales entre UDP et TCP.

TCP dans les grandes lignes

TCP, qui signifie Transmission Control Protocol, Protocole de contrôle de transmission en anglais, est un protocole de la couche transport défini par les RFC 793, 1122, 1323 et aussi 2581.
Tout comme UDP, le but de TCP est d’assurer la transmission des SDU. Tout comme UDP, TCP nous offre des services de multiplexage et démultiplexage. La différence se situe fondamentalement dans ce que nous avons appelé « principe de transmission fiable »

Dans notre exemple de transmission des lettres, Pierre et Jean, avons-nous dit, représentent un protocole de transmission. Nous avons dit que ces derniers pouvaient offrir un service fiable en garantissant à leurs frères que les lettres arriveraient à la poste.

Dans notre exemple impliquant les files de taxis, nous avons dit qu’il était impossible de garantir que chaque groupe arriverait à la fête en raison des imprévus.

UDP, comme nous l’avons vu, est un protocole orienté transaction, par conséquent, il ne peut garantir que les données transmises arriveront à destination. TCP, en revanche, étant un protocole orienté-connexion (vous vous en souvenez ?) par le principe de la poignée de main (handshake) établit une connexion au préalable, entre les processus avant de débuter la transmission.

Le titre de ce chapitre qualifie TCP comme étant un protocole pessimiste, vous vous demandez certainement pourquoi. TCP « n’espère pas » comme UDP, que les données arriveront a destination, mais TCP, en protocole responsable, s’assure, que les données transmises arriveront à bon port. Cette garantie est possible grâce à ses propriétés de détection d’erreur, contrôle de séquences, retransmissions, accusé de réception (très important).

L’état de connexion avec TCP

Nous avons dit que TCP était un protocole orienté-connexion, mais qu’est ce que ca veut dire concrètement ? Pour qu’il y’ait échange ou transmission entre deux applications utilisant TCP comme protocole de transport, il faut établir une connexion TCP (TCP connection en anglais). La poignée de main (handshake), ou le genre de connexion que TCP établit est aussi appelé « three-way handshake ». En gros, cela veut dire que la connexion se fait en trois étapes. Vous vous souvenez du concept full-duplex et half-duplex ? Nous vous recommandons de relire le chapitre traitant de ces notions combien précieuses. En effet, TCP est un protocole full-duplex, ce qui implique qu’une communication bidirectionnelle et simultanée est possible dans une connexion TCP.
En guise de rappel, un système de communication half-duplex veut dire que la communication se fait dans un sens unique. L’hôte A transmet à l’hôte B ou vice versa, mais en aucun cas les deux peuvent transmettre au même moment, simultanément. Cet avantage ne nous est offert que dans un système de transmission full-duplex, et ca tombe bien parce que TCP est un protocole full-duplex. 
Voici comment s’établit une connexion suivant le principe de « three-way handshakre ».
Supposons que 2 processus de deux hôtes différents veulent s’échanger des informations. Il faut, bien entendu, qu’un hôte initialise la connexion (demande à l’autre hôte la permission de communiquer). Comme vous le savez, l’hôte qui initialise la connexion est le client, et celui qui accepte est le serveur. ;)

Le client et le serveur s’échangent donc des unités de données appelées des segments TCP (TCP segments en anglais) qui sont composés bien entendu d’un entête et d’un espace de données (data area en anglais). Vous comprendrez toutes ces choses plus facilement, lorsque nous inspecteront la structure d’un segment TCP.
Pour nous assurer que vous n’aurez pas de difficulté à assimiler le three-way handshake, nous allons y aller petit à petit en détaillant chaque étape.
C’est parti, analysant petit à petit le processus du fameux « three-way handshkae ».
Le long de notre analyse, nous allons considérer 6 paramètres extrêmement importants pour saisir la procédure d’établissement d’une connexion TCP entre un client et un serveur. Ces paramètres sont :

  • Etat du serveur

  • Etat du Client

  • Segment transmis par le client

  • Segment transmis par le serveur

  • Etat de transition du client

  • Etat de transition du serveur

Les noms des paramètres sont assez évocateurs. L’état du serveur/client définit dans quel état se trouve le client/serveur dans l’établissement de la connexion. Le segment transmis par le client/serveur parle de la constitution du segment TCP constitué d’un entête et d’une donnée que les deux s’échangent le long de la procédure. Finalement, l’état de transition du client/serveur définit simplement un état entre deux états. :-‘ C’est maladroit de le dire ainsi, grossièrement, lorsque le serveur par exemple, passe de l’état fermé (closed) à l’état ouvert, l’état de transition ici est l’état d’écoute (Listen). En effet pour pouvoir ouvrir ou initialiser une connexion, il faut bien que le serveur écoute le port auquel il est attaché. On dit que cet état d’écoute est un état de transition. ;)

Vous êtes prêts? C’est parti ! :pirate:

Etape 1

Pour faire une demande d’initialisation de connexion, le client envoi un segment TCP qui ne contient QUE l’entête. Il est important de noter que le premier segment TCP envoyé dans le three-way handshake n’a aucun payload, mais seulement un entête

Et y’a quoi dans cet entête alors ?

Nous y arrivons ! L’entête contient un flag (drapeau) de synchronisation : Flag SYN (avec SYN diminutif de SYNchroniser). L’entête contient aussi le numéro de port TCP du serveur, ce qui est logique, car le numéro de port, est pour une application, ce que l’adresse IP est pour un hôte. ;)
Après l’envoi de ce premier segment TCP, le client se met dans un état SYN_SENT. Pour ceux qui n’ont pas séché leurs cours d’anglais ( ^^), vous comprenez tout de suite que SYN_SENT signifie que le segment TCP ayant le flag SYN a été envoyé.

Le serveur de son côté, comme vous le savez maintenant, est en état Listen. Il écoute sur le numéro de port, attendant une demande de connexion. Dès qu’Il reçoit le segment TCP envoyé par le client (celui qui n’a qu’un entête et un flag SYN), il envoie un segment TCP vers le client pour confirmer la réception du flag SYN. Ce segment également n’est constitué que d’un entête portant deux flags : SYN (chronize) et ACK(nowledge). Finalement, le serveur change d’état et passe de Listen à SYN_RCVD. RCVD est le diminutif de received (reçu en anglais). Cet état confirme que le segment TCP portant le flag SYN a été reçu.

Etape 2 et 3

Le client reçoit le segment TCP et analyse l’entête. Il remarque qu’il contient les flags SYN et ACK, qui sont pour lui des indicateurs que le serveur a été gentil accepte d’initialiser une connexion avec lui. La connexion passe donc de Closed (fermée) à established (établie). Il conclut la procédure en envoyant un segment TCP avec le flag ACK au serveur en guise de remerciement. ( :p ) Sérieusement, ce dernier ACK envoyé est la conclusion de la procédure et va également mettre le serveur en état de connexion établie (established state).
Voila ! Maintenant que les deux (client et serveur) ont établi une connexion, cette dernière peut être utilisée pour transmettre des informations

En résumé, voici deux images dont l’une en .gif pour vous permettre de mieux visualiser la procédure.

Image utilisateur
Image utilisateur

Voilà pour l'établissement, mais maintenant, il faut transmettre des données ! À quoi cela sert d'être connecté, sinon ? ^^

Séquence émotion et acquittement

Comment TCP s'assure que les données sont bien arrivées ? Grâce à des numéros de séquence ! Lorsqu'une connexion TCP est initialisée, un nombre est généré : l'ISN (cela peut être un zéro ou un nombre aléatoire suivant les systèmes). Quand des données sont envoyées, ce numéro de séquence est augmenté d'autant d'octets de données qui sont envoyés.

Voici un exemple :

Image utilisateur

Capture d'échange de données avec TCP

Sur cette capture, nous pouvons voir que l'hôte 192.168.1.56 a établi une connexion TCP avec 192.168.1.62. Les trois premières trames représentent le 3-way handshake. La quatrième trame, en bleu, est un envoi de données au travers de cette connexion. Regardez les valeurs de Seq et Len. Nous partons d'un numéro de séquence qui est de 1 et nous envoyons 6 octets de données. Le serveur nous répond avec un ACK (accusé de réception), ce qui signifie qu'il a bien reçu quelque chose. Il précise la valeur 7 dans le champ "Ack", car il a additionné le numéro de séquence du segment reçu (1) avec la longueur des données du segment en question (6), ce qui fait bien 7. Le client sait donc que son segment a bien été reçu.

Que se serait-il passé si le segment n'avait pas été reçu ? Pour une raison quelconque, il aurait pu être perdu en cours de route. Dans ce cas, si le client ne reçoit pas d'accusé de réception, il renvoie automatiquement le même segment au bout d'un temps défini appelé RTO. Ce temps est calculé dynamiquement. Si vous voulez vous amuser à comprendre ce mécanisme, vous pouvez lire la RFC 2988.

Lors de l'établissement en trois phases, aucune donnée n'est transmise, et pourtant, le serveur répond avec un Ack de 1 alors que le numéro de séquence du segment envoyé est 0 !

Si vous l'avez remarqué, chapeau ! Effectivement, le numéro de séquence des deux machines est augmenté de 1 lors du 3-way handshake.

Le principe des numéros de séquence et d'acquittement est fondamental pour comprendre TCP. Pourtant, ce protocole a plus d'un tour dans son sac et permet d'effectuer tout un tas de contrôle pour optimiser le traitement des communications. Avant d'aller plus loin, voyons comment est structuré un segment TCP pour visualiser toutes les possibilités qu'il offre.

Structure d'un segment

Visualisons les différents champs d'un segment TCP :

Image utilisateur

Tableau tiré de la page Wikipédia "Transmission Control Protocol", visualisée le 22 septembre 2012

La plupart des informations transmises par TCP comme la fenêtre ou la somme de contrôle seront étudiés dans les prochains chapitres. Pour conclure cette sous-partie, nous allons revenir sur les états de connexion mais lorsqu'une connexion est fermée.

[flags et états - netstat - socklab (TP) - à continuer]

TCP et UDP : qui remporte le clash?

m

L’aventure ne s’arrête pas la. Ce chapitre nous a permis d’étudier les faiblesses du protocole UDP, et surtout de comprendre pourquoi TCP est le protocole de transport le plus utilisé. En outre, vous avez, nous l’espérons, saisi que dans certaines circonstances, il est préférable d’utiliser UDP. Le but de la connaissance théorique des protocoles est justement de vous permettre d’être en mesure de choisir celui qui correspond le mieux aux contraintes de votre projet. TCP, comme nous l’avons souligné, est un protocole très riche, c’est pour cela que nous allons l’examiner dans de plus profonds détails en analysant les différents services qu’Il offre tels que le contrôle de congestion, contrôle de séquences, etc.

Exemple de certificat de réussite
Exemple de certificat de réussite