# Etude d'un protocole fiable : TCP

Marie-Claude Vialatte

## Numérotation, acquittement : explication simplifiée

> La fiabilisation du transfert de données est obtenue de la manière suivante :

> - chaque PDU de données est identifiée par un numéro, qui est le numéro du 1er octet de données qu'elle transporte. Il est placé dans le champ `seq` de la PDU

> - pour chaque sens de transmission, le numéro à utiliser pour la 1ère PDU est défini lors de l'établissement de la connexion (champ `seq` de la 1ère PDU émise +1).

> - pour chaque sens de transmission, le numéro à utiliser pour les autres PDU est égal à : (n° de la PDU précédente) + (nombre d'octets de données transportés par la PDU précédente)

>   > Chaque octet transmis dans un sens de transmission peut alors être désigné par son numéro qui représente sa position dans le flux (stream) d'octets transmis dans ce sens de transmission.

> Chaque entité-TCP possède 2 variables internes :
> - `V(S)` le n° qui devra être affecté à la prochaine PDU à émettre
> - `V(R)` le n° qui devrait avoir la prochaine PDU attendue en réception

> ### Chaque fois qu'une entité-TCP émet une PDU de données :

> - elle copie la valeur de `V(S)` dans le champ `seq` de la PDU
> - elle augmente la valeur de `V(S)` du nombre d'octets de données placés dans la PDU (éventuellement 0)
> - elle copie la valeur de `V(R)` dans le champ `ack`
> - elle mémorise dans un buffer d'émission les octets de données (copiés dans la PDU) "au cas où..."
> - elle arme un temporisateur (timer) à une valeur qui dépend de mesures du délai d'aller et retrour (RTT : Round Trip Time)
> Si le temporisateur arrive à échéance, refaire une tentative d'émission des octets restants dans le buffer d'émission.

> ### Chaque fois qu'une entité-TCP reçoit une PDU de données :

> - elle compare les valeurs du champ `seq` de la PDU et de sa variable `V(R)`.

>   `seq = V(R)` | s'il y a des octets de données, ils sont mémorisés dans le buffer de réception, à la place calculée à partir de la valeur de `seq`, donc à la suite des octets précédemment reçus
>   `seq > V(R)` | les octets de numéro `V(R)` à `seq-1` se sont perdus. ==> la PDU reçue est ignorée. ==> éventuellement une PDU vide est envoyée
>   `seq < V(R)` | les octets de numéro `seq` à `V(R)-1` ont déjà été reçus. Pas de problème, les octets de données sont mémorisés dans le buffer de réception à la place calculée à partir de la valeur de `seq`

>   Note : la mémorisation dans le buffer de réception suppose qu'il y a assez de place.
>     Si ce n'est pas le cas, la PDU reçue est ignorée, et une PDU vide peut être envoyée
> - elle compare les valeurs du champ `ack` et de sa variable `V(S)`

>   `ack = V(S)` | tous les octets (précédemment émis) ont été reçus ==> les enlever du buffer d'émission ==> désactiver le temporisateur
>   `ack < V(S)` | seuls les octets jusqu'au numéro `ack` (précédemment émis) ont été reçus ==> enlever les octets reçus du buffer d'émission
>   `ack > V(S)` | il y a un problème ! il vaut mieux fermer la connexion, pour éventuellement repartir sur des bases saines.