Author: Christian.Queinnec@lip6.fr

## Protocoles de communication

Les différentes communications des client-serveur décrits à la section précédente consistent à envoyer une chaîne de caractères terminée par un retour-chariot et à en recevoir une autre. Bien que simples elles définissent un protocole. Dès que l'on veut communiquer des valeurs plus complexes : un flottant, une matrice de flottants, un arbre d'expressions arithmétiques, une fermeture ou un objet, se pose le problème du codage de ces valeurs. Plusieurs solutions existent selon la nature des programmes communicants que l'on caractérise par : le langage d'implantation, l'architecture machine et dans certains cas le système d'exploitation. En effet selon l'architecture machine les entiers seront représentés de différentes manières (bits de poids fort à gauche, à droite, bits de tag, taille du mot machine). Pour communiquer une valeur entière cohérente entre différents programmes, il est nécessaire d'avoir une représentation commune des valeurs que l'on appelle représentation externe1. Les valeurs plus structurées, comme les enregistrements, doivent également avoir une représentation externe. On rencontre néanmoins un problème lorsque certains langages autorisent des constructions, comme les champs de bits en C, qui n'existent pas dans les autres langages. Le passage de valeurs fonctionnelles ou d'objets, qui contiennent une partie code, pose une nouvelle difficulté pour le chargement de ce code. Celui-ci est-il compatible (code-octet) entre l'envoyeur et le récepteur, et existe-t-il un mécanisme de chargement dynamique de code? En règle générale on simplifiera ce problème en supposant que le code existe des deux côtés. Ce n'est pas lui qui est transmis, mais des informations permettant de le retrouver. Pour un objet on communique ses variables d'instance et son type ce qui permet d'en retrouver les méthodes. Pour une fermeture on envoie son environnement et l'adresse de son code. Ce qui implique que les deux programmes communicants sont le même exécutable.
Une deuxième difficulté provient de la complexité des échanges liée à la nécessité de synchroniser les communications mettant en jeu plusieurs programmes.
On présente tout d'abord des protocoles texte, pour ensuite discuter de l'acquittement et des limites de temps entre requêtes et réponses. Nous évoquons aussi la difficulté de communiquer des valeurs internes d'un programme en particulier dans le cadre de l'interopérabilité entre programmes issus de différents langages.

### Protocole texte

Les protocoles texte, c'est à dire la communication en format ASCII, sont les plus courants car les plus simples à mettre en oeuvre et les plus portables. Par contre quand le protocole se complique, il peut être lourd à implanter. Dans ce cadre là on définit une grammaire pour décrire le format de communication. Celui-ci peut être riche, mais ce sera aux programmes communicants de faire le travail de codage et d'interprétation des chaînes reçues.
En règle générale, l'utilisation d'une application réseau ne permet pas de voir les différentes couches de protocoles utilisées. C'est typiquement le cas du protocole HTTP permettant à un navigateur de communiquer avec un site Web.

#### Protocole HTTP

On rencontre fréquemment le terme <<HTTP>> dans les publicités. Il correspond au protocole de communication des applications du Web. Celui-ci est complètement décrit sur la page du consortium W3 :

### Lien

http://www.w3.org

Ce protocole est utilisé pour transporter les requêtes émises par les navigateurs (Communicator, Explorer, Opera, etc) et pour retourner le contenu de la page demandée. Une requête effectuée par un navigateur contient le nom du protocole (HTTP), le nom de la machine (www.ufr-info-p6.jussieu.fr), et l'arborescence de la page demandée (/Public/Localisation/index.html). Cet ensemble de trois composants permet de définir une URL (Uniform Ressource Locators) :

    http://www.ufr-info-p6.jussieu.fr/Public/Localisation/index.html

Quand une telle URL est demandée à partir d'un navigateur, une connexion via une socket est établie entre le navigateur et le serveur s'exécutant sur la machine indiquée, par défaut sur le port 80. Puis le navigateur envoie une requête au format HTTP, proche de la suivante :

    GET /index.html HTTP/1.0

Alors le serveur lui répond dans le protocole HTTP, l'en-tête :

    HTTP/1.1 200 OK
    Date: Wed, 14 Jul 1999 22:07:48 GMT
    Server: Apache/1.3.4 (Unix) PHP/3.0.6 AuthMySQL/2.20
    Last-Modified: Thu, 10 Jun 1999 12:53:46 GMT
    ETag: "4c801-e4f-375fb55a"
    Accept-Ranges: bytes
    Content-Length: 3663
    Connection: close
    Content-Type: text/html

Cet en-tête indique que la requête est acceptée (code 200 OK), la nature du serveur, la date de modification de la page, la longueur de la page envoyée et le type du contenu qui va suivre. Sans la précision de la version de protocole (HTTP/1.0) de la commande GET, seule la page HTML est transférée. La connexion suivante avec telnet permet de voir ce qui est effectivement transmis :

    $ telnet www.ufr-info-p6.jussieu.fr 80
    Trying 132.227.68.44...
    Connected to triton.ufr-info-p6.jussieu.fr.
    Escape character is '^]'.
    GET

    <!-- index.html -->
    <HTML>
    <HEAD>
    <TITLE>Serveur de l'UFR d'Informatique de Pierre et Marie Curie</TITLE>
    </HEAD>
    <BODY>

    <IMG SRC="/Icons/upmc.gif" ALT="logo-P6" ALIGN=LEFT HSPACE=30>
    Unit&eacute; de Formation et de Recherche 922 - Informatique<BR>
    Universit&eacute; Pierre et Marie Curie<BR>
    4, place Jussieu<BR>
    75252 PARIS Cedex 05, France<BR><P>
    ....
    </BODY>
    </HTML>
    <!-- index.html -->

    Connection closed by foreign host.

La connexion se referme dès que la page est copiée. Le protocole de base est en mode texte ainsi que le langage à interpréter. On note que les images ne sont pas transmises avec la page. C'est au navigateur, lors de l'analyse syntaxique de la page HTML, de remarquer les ancres et les images (voir la balise `IMG` de la page transmise). À ce moment là, le navigateur envoie une nouvelle requête pour chaque image rencontrée dans le source HTML, il y a donc une nouvelle connexion par image. Ces images sont affichées dès qu'elles sont reçues. C'est pour cette raison que les images s'affichent souvent en parallèle.
Le protocole HTTP est assez simple, mais il véhicule une information dans le langage HTML qui lui est plus complexe.

### Protocoles avec acquittement et limite de temps

Quand le protocole est complexe, il est utile que le récepteur d'un message indique à l'envoyeur qu'il a bien reçu le message et que celui-ci est grammaticalement correct. En effet le client peut être en attente bloquante de réponse avant de poursuivre ses tâches. Si la partie du serveur traitant cette requête a une difficulté d'interprétation du message, le serveur doit l'indiquer au client plutôt que d'oublier cette requête. L'exemple du protocole HTTP a une gestion de code d'erreurs. Une requête correcte renvoie le code 200. Une requête mal formée ou la demande d'accès à une page non autorisée renvoie un code d'erreur 4xx ou 5xx selon la nature de l'erreur. Ces codes d'erreur permettent au client de savoir ce qu'il a à faire et au serveur de tenir des fichiers de compte-rendu précis sur la nature des incidents.
Lorsqu'un serveur est dans un état incohérent, il peut toujours accepter une connexion d'un client, mais risque de ne jamais lui envoyer de réponse sur la socket. Pour éviter ces attentes bloquantes, il est utile de fixer une limite de temps pour la transmission de la réponse. Passé ce délai, le client suppose que le serveur ne répondra plus. Alors le client peut fermer cette connexion pour passer à la suite de son travail. C'est ainsi que les navigateurs WWW font. Quand une requête n'a pas de réponse au bout d'un certain temps, le navigateur décide de l'indiquer à l'utilisateur. Objective CAML possède des entrées-sorties avec limite de temps. Dans le module `Thread`, les fonctions `wait_time_read` et `wait_time_write` suspendent l'exécution de la tâche jusqu'au moment où un caractère peut être lu ou écrit, cela dans un certain délai. Elles prennent en entrée un descripteur de fichier et un délai exprimé en secondes : Unix.file_descr -> float -> bool. Si le délai a été dépassé la fonction retourne `false`, sinon l'entrée-sortie peut être effectuée.

### Transmission de valeurs en représentation interne

L'intérêt de la transmission de valeurs en représentation interne est de simplifier le protocole. Il n'y a plus besoin de coder ni de décoder les données dans un format texte. Les difficultés inhérentes à l'envoi-réception de valeurs en représentation interne sont les mêmes que celles rencontrées pour les valeurs persistantes (voir le module `Marshal` page ??). En effet lire ou écrire une valeur dans un fichier est équivalent à recevoir ou émettre cette même valeur sur une socket.

#### Valeurs fonctionnelles

Dans le cas de transmission d'une fermeture entre deux programmes Objective CAML, le code de la fermeture n'est pas envoyé, seul son environnement et son pointeur de code (voir figure 12.9 page ??) le sont. Pour que cela fonctionne il est nécessaire que le serveur possède le même code au même emplacement. Ce qui implique que le même programme tourne en tant que serveur et en tant que client. Rien n'empêche cependant que ces deux programmes soient en train d'exécuter des parties de code différentes. On adapte alors le service de calcul matriciel en envoyant la fermeture contenant dans son environnement les données à calculer. À la réception le serveur applique cette fermeture à () et le calcul se déclenche.

### Interopérer avec d'autres langages

L'intérêt des protocoles texte est qu'ils sont indépendants des langages d'implantation des clients et des serveurs. En effet le code ASCII est toujours connu des langages de programmation. Ensuite c'est au client et au serveur de savoir analyser syntaxiquement les chaînes de caractères transmises. Un exemple d'un tel protocole ouvert est la simulation de joueurs de football, appelée RoboCup.

#### Robots footballeurs

Une équipe de football joue contre une autre équipe. Chaque membre d'une équipe est un client du serveur arbitre. Les joueurs d'une même équipe ne peuvent pas communiquer directement entre eux. Ils doivent passer par le serveur, qui retransmet le dialogue. Le serveur indique selon la position du joueur une partie du terrain. Toutes ces communications s'effectuent selon un protocole texte. La page de présentation du protocole, du serveur et de certains clients :

### Lien

http://www.robocup.org/

Le serveur est écrit en C. Les clients sont écrits dans différents langages : C, C++, SmallTalk, Objective CAML, etc. Rien n'empêche d'ailleurs une équipe de posséder des joueurs issus de différents langages.
Ce protocole répond aux besoins d'interopérabilité entre programmes de différents langages d'implantation. Il est relativement simple, mais il nécessite un analyseur syntaxique particulier pour chaque famille de langages.