Soutien aux Développeurs


Notice TCP/UDP
par François Piette

      La plupart des personnes ne savent pas quel protocole choisir entre TCP et UDP quand ils commencent à travailler avec TCP/IP. Et quand ils ont choisi, ils commencent à avoir des problèmes parce que ça ne marche pas comme ils pensaient.

      Ce document essaye d'expliquer en termes simples le pour et le contre de chacun dans l'optique du composant gratuit TWSocket pour Delphi et C++Builder.



ADRESSAGE
      TCP et UDP emploient le même shéma d'adressage. Une adresse IP (nombre de 32 bits, toujours écrit en quatre nombres de 8 bits exprimé en nombres décimaux à 3 chiffres non signés, séparés par des points comme 193.174.25.26) et un numéro de port (un nombre de 16 bits exprimé en nombre décimal non signé).

      L'adresse IP est utilisé dans le protocole de bas niveau (IP) pour acheminer le datagramme à l'hôte correct sur le réseau indiqué. Le numéro de port est alors utilisé pour acheminer le datagramme au processus hôte correct (programme sur l'hôte).

      Pour un protocole donné (TCP ou UDP), un processus hôte unique peut exister à un moment donné pour recevoir des données envoyées au port défini. D'habitude un port est dédié à un processus.


UDP
      UDP signifie Protocole de Datagramme Utilisateur. Il est décrit dans STD-6/RFC-768 et fournit une voie de communication d'hôte à hôte sans connexion. UDP a un faible entête; chaque paquet sur le réseau est composé d'une petite en-tête et de données. Il est appelé datagramme UDP.

      UDP préserve les limites de datagramme entre l'expéditeur et le récepteur. Cela signifie que le socket de réception recevra un événement OnDataAvailable pour chaque datagramme envoyé et la méthode Reception renverra un datagramme complet pour chaque appel. Si le buffer est trop petit, le datagramme sera tronqué. Si le buffer est trop grand, seul un datagramme est renvoyé, ce qui reste du buffer n'est pas touché.

      UDP est sans connexion. Cela signifie qu'un datagramme peut être envoyé à tout moment sans avis préalable, négociation ou préparation. Il envoie juste le datagramme en espérant que le récepteur soit capable de l'interpréter.

      UDP est un protocole incertain. Il n'y a absolument aucune garantie que le datagramme soit livré à l'hôte de destination. Mais à vrai dire, le taux d'échec est très bas sur Internet et quasi nul sur un réseau local, sauf s'il est saturé.

      Non seulement le datagramme peut ne pas être livré, mais il peut aussi être livré dans un ordre incorrect. Cela signifie que vous pouvez recevoir un paquet avant un autre, même si le deuxième a été envoyé avant le premier que vous avez reçu. Vous pouvez également recevoir deux fois le même paquet.

      Votre application doit être préparée pour faire face à toutes ces situations: datagramme manquant, datagramme double ou datagramme dans un ordre incorrect. Vous devez programmer la détection d'erreurs et leurs corrections. Par exemple, si vous devez transférer des fichiers, vous feriez mieux de mettre en place une sorte de protocole Zmodem.

      Les principaux avantages d'UDP est que les limites de datagramme sont respectée, vous pouvez transmettre et c'est rapide.

      L'inconvénient principal est le manque de fiabilité, ce qui complique le développement du programme.


TCP
      TCP signifie Protocole de Contrôle de Transmission. Il est décrit dans STD-7/RFC-793. TCP est un protocole orienté connexion qui est responsable de la fiabilité de la communication entre deux processus. L'unité de données transférées est appelée un flot, qui est simplement une séquence d'octets.

      Etre orienté connexion signifie qu'avant de transmettre des données, vous devez ouvrir la connexion entre les deux hôtes. Les données peuvent être transmises en full duplex (envoyer et recevoir sur une seule connexion. Quand le transfert est terminé, vous devez clore la connexion pour libérer les ressources système. De chaque côté on sait quand la session débute et quand elle se termine. La transmission de données ne peut pas avoir lieu tant que les 2 hôtes n'ont pas approuvé la connexion. La connexion peut être fermée par chacun des hôtes; l'autre en est notifié. Il est décidé si on termine correctement ou si on interrompt seulement la connexion.

      Etre orienté flot signifie que les données formes une séquence inconnue d'octets. Il n'y a rien à faire pour avoir des données apparentes. Le récepteur n'a aucun moyen de savoir comment les données ont été réellement transmises. L'expéditeur peut envoyer beaucoup de petits paquets de données et le récepteur seulement recevoir un gros paquet, ou l'expéditeur peut envoyer un gros paquet, le récepteur le recevant en un certain nombre de paquets plus petits. La seule chose que l'on garantit est que toutes les données envoyées seront reçues sans une erreur et dans l'ordre correct. Si une erreur se produit, elle sera automatiquement corrigée (retransmise selon le besoin) ou l'erreur sera notifiée si elle ne peut pas être corrigée.

      Au niveau du programme, le flot TCP ressemble à un fichier linéaire. Quand vous écrivez des données dans un fichier linéaire et le relisez plus tard, vous êtes absolument incapables de savoir si les données ont été écrites en une seule fois ou en plusieurs. À moins que vous n'écriviez quelque chose de spécial pour identifier les limites des enregistrements, vous ne pouvez rien faire pour l'apprendre par la suite. Vous pouvez, par exemple, utiliser CR ou CR LF pour délimiter vos enregistrements comme un fichier texte linéaire.

      Au niveau programmation, TWSocket est assez simple à utiliser. Pour envoyer des données, vous avez seulement à appeler la méthode Send (ou n'importe quelle variante comme SendStr) pour transmettre les données. TWSocket le stockera dans un buffer avant qu'il ne puisse être réellement transmis. Finalement les données seront envoyées en arrière-plan (la méthode Send se réinitialise immédiatement sans attendre que les données soient transmises) et l'événement OnDataSent sera généré une fois que le buffer sera vidé.

      Pour recevoir les données, le programme doit attendre l'événement OnDataAvailable. Cet événement est déclenché chaque fois qu'un paquet de données vient du niveau inférieur. L'application doit appeler la méthode Receive pour obtenir les données des buffers de bas niveau. Vous devez recevoir toutes les données disponibles ou votre programme entrera dans une boucle sans fin car TWSocket redéclenchera OnDataAvailable si vous n'avez pas reçu toutes les données.

      Comme les données sont un flot d'octets, votre application doit être préparée à recevoir des données envoyées par l'expéditeur, fragmentées en plusieurs gros paquets ou fusionnées dans de plus gros paquets. Par exemple, si l'expéditeur a envoyé "Hello et ensuite "World!", il est possible d'obtenir un seul événement OnDataAvailable et recevoir "Hello World!" dans un paquet, ou obtenir deux événements, un pour "Hello " et un autre pour "World!". Vous pouvez même recevoir des paquets plus petits comme "Hel", "lo wo" et "rld!". Ce qui arrive dépend de la densité du trafic, des algorithmes de routage, des erreurs aléatoires et de beaucoup d'autres paramètres que vous ne pouvez pas contrôler.

      Pour ce qui est des applications client/serveur, la plupart des applications doivent connaître les limites de commande avant de pouvoir traiter les données. Comme les limites de données ne sont pas toujours préservées, vous ne pouvez pas supposer que votre serveur recevra une seule commande complète dans un unique événement OnDataAvailable. Vous pouvez recevoir uniquement une partie de requête ou peut-être deux ou plusieurs requêtes fusionnées en un gros paquet. Pour surmonter cette difficulté, vous devez employer des délimiteurs.

      La plupart des protocoles TCP/IP, comme SMTP, POP3, FTP et quelques autres, utilisent le couple CR/LF comme délimiteur de commande. Chaque requête du client est envoyée telle quelle avec le couple CR/LF ajouté. Le serveur reçoit les données comme elles arrivent, les assemblent dans un buffer de réception, scanne les couples CR/LF pour extraire des commandes du flot reçu, et les enlève du buffer de réception.

      Utiliser CR/LF comme délimiteur est très pratique car vous pouvez tester votre serveur en utilisant l'application "telnet".

      - François Piette
Merci à Tony Wells et Don Peoples pour la version anglaise de ce texte.