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é de Formation et de Recherche 922 - Informatique<BR>
Université 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.