Une idée fausse courante consiste à croire que le protocole TCP garantit la livraison des données. En réalité, le protocole TCP garantit qu'il livrera les données à la pile TCP de l'hôte destinataire ou signalera une erreur à l'application expéditrice. Malheureusement, le rapport d'erreur n'indique pas la quantité de données réellement livrée. Il existe également une différence significative entre la pile TCP destinataire et l'application destinataire.
Il existe deux scénarios d'échec de base. Dans le premier, la pile TCP émettrice ne reçoit pas d'accusés de réception TCP pour les données qu'elle transmet. Dans ce scénario, l'application émettrice peut continuer à appeler send pour ajouter davantage de données dans le tampon d'envoi de la pile TCP. Une fois que la pile TCP a expiré la transmission, le prochain envoi (ou réception) appelé par l'application émettrice indiquera l'erreur ETIMEDOUT. L'application sait désormais qu'il y a eu un problème, mais elle n'a aucune idée de la quantité de données qui a été transmise avec succès. Le succès signifie que la pile TCP émettrice a reçu un accusé de réception pour les données de la pile TCP réceptrice.
Dans le deuxième scénario, la pile TCP émettrice transmet les données et reçoit une réinitialisation au lieu d'un accusé de réception. La réinitialisation peut indiquer que la pile TCP réceptrice a fermé le socket ou qu'un périphérique réseau, peut-être un pare-feu, a expiré. La prochaine fois que l'application émettrice appelle send (ou receive), l'erreur ECONNRESET est indiquée. On pourrait penser que dans ce scénario, l'application émettrice pourrait en déduire que seules les données du dernier appel send ont échoué, mais ce serait une erreur. Il est possible que la pile TCP émettrice ait mis en mémoire tampon les données de plusieurs appels send dans un seul segment TCP et que ce segment ait déclenché la réinitialisation, ou qu'une série de segments TCP ait été envoyée avant que la réinitialisation, déclenchée par le premier segment de la série, ne revienne à l'émetteur. Tout ce que l'application émettrice peut déduire, c'est que toutes les données n'ont pas été transmises avec succès.
Il existe un troisième scénario d'échec qui n'a rien à voir avec la pile TCP (envoi ou réception) ou le réseau. Supposons que l'application réceptrice comporte un bogue qui l'empêche de lire les données. La pile TCP réceptrice continuera à recevoir les données et à envoyer des accusés de réception TCP jusqu'à ce que le tampon de réception TCP soit plein. Cela peut toutefois représenter jusqu'à 64 Ko de données (ou plus si la mise à l'échelle de la fenêtre TCP est prise en charge). Si l'application réceptrice doit être redémarrée, toutes les données du tampon de réception TCP seront perdues. La pile TCP réceptrice devrait (mais ne le fait pas nécessairement) envoyer une réinitialisation à la pile TCP émettrice lorsque l'application réceptrice est fermée. Elle enverra une réinitialisation la prochaine fois qu'elle recevra un segment pour la connexion désormais fermée. Du point de vue de l'application d'envoi, cela ressemble au deuxième scénario. Cependant, cela souligne que même si la pile TCP réceptrice accuse réception des données, en cas d'erreur, l'expéditeur ne peut pas supposer en toute sécurité que l'application réceptrice a lu les données.
La conclusion à tirer de ces scénarios d'échec est que, sans accusé de réception au niveau de la couche application, un délai d'attente de transmission ou une erreur de réinitialisation indique qu'une partie, voire la totalité, des données transmises n'a peut-être pas été lue par l'application réceptrice. C'est pourquoi je recommande que toutes les applications incluent des accusés de réception au niveau de la couche application, soient prêtes à rétablir une connexion et à retransmettre les données non confirmées, et soient capables de traiter les données en double, car ce qui a pu être perdu, c'est l'accusé de réception.
