Université Joseph Fourier
DEUG STPI - 2ème année - IUP MIAG - 1ère année
Introduction aux systèmes et réseaux
 
Réalisation de systèmes client-serveur
avec Tcl-DP
Tcl-DP (Distributed Processing) est l'extension répartie de Tcl. Elle permet de réaliser très simplement des systèmes client-serveur et des systèmes à objets répartis. Cette fiche examine les systèmes client-serveur. Une autre fiche présente les objets répartis.

Pour utiliser Tcl-DP, il faut appeler wish, l'interprète (shell) de Tcl :

wish si on veut aussi utiliser TK (graphique),

ou wish -notk si on n'utilise pas TK.

La premire ligne des programme Tcl-DP doit contenir la commande suivante qui permet d'utiliser l'extension DP :
package require dp
Dans la pratique, s'agissant d'informatique répartie, on utilisera deux processus (ou plus), chacun exécutant son propre interprète. Ces processus pourront être sur des machines différentes, ou sur la même machine (le principe est exactement le même). Dans tous les cas, utiliser une fenêtre différente par processus.

Schéma client-serveur

Un schéma client-serveur met en jeu deux processus : le client, qui demande un service, et le serveur, qui réalise le service. Dans le cadre de ce travail, un service est simplement l'exécution d'une procédure. Lorsque le client et le serveur sont sur deux machines différentes, on parle d'appel de procédure à distance (en anglais : Remote Procedure Call, ou RPC). Pour le client, l'effet de l'appel de procédure à distance doit être le plus voisin possible de l'effet du même appel réalisé localement. Trois remarques importantes :
 

 
 

Réalisation du schéma client-serveur en Tcl-DP

Tcl-DP fournit la possibilité de réaliser un appel de procédure à distance. Pour cela, il fournit trois commandes : dp_MakeRPCServer permet de créer un serveur, dp_MakeRPCClient permet à un client d'identifier un serveur et d'établir une liaison avec lui, et dp_RPC réalise l'appel proprement dit.

Pour bien comprendre le fonctionnement de ces commandes, le point-clé est la désignation : le client doit pouvoir identifier le serveur (pour lui envoyer sa demande), et le serveur doit pouvoir identifier le client (pour lui répondre). Rappelons que le client et le serveur sont des processus. Leur désignation comporte donc deux parties : identité de la machine, identité du processus sur la machine.

1) Désignation d'une machine. Une machine peut être désignée :

  • (de préférence) par son nom symbolique (par exemple thales.ujf-grenoble.fr) ; si on est déjà dans le domaine ujf-grenoble.fr (ce qui est ici le cas), alors il suffit de donner le nom local thales.
  • par son adresse IP. Noter au passage que la traduction du nom symbolique en adresse IP est un service particulier (Domain Name Service, ou DNS) utilisé par tout service réparti.
  • 2) Désignation d'un processus sur une machine. On pourrait utiliser le numéro du processus (pid sous Unix). Mais on ne le fait pas, pour plusieurs raisons : cela nécessiterait, depuis l'extérieur, d'avoir accès à des informations internes ; et surtout cela rendrait difficile tout changement, par exemple l'arrêt du processus serveur et son redémarrage sous un autre numéro. On utilise donc une désignation indirecte : le numéro de porte. Les portes (en anglais port) sont des "points d'entrée" sur une machine. Lorsqu'on créé un processus serveur, on l'associe à une porte sur sa machine, et le client doit s'adresser à cette porte. Un certain nombre de portes (en principe les numéros inférieurs à 1024) sont réservées par convention à des fonctions particulières (par exemple la porte n° 80 est réservée au serveur Web, etc). Donc, utiliser des portes de numéro supérieur à 1024.

    Remarques a) Comme c'est le client qui appelle le serveur, il faut toujours créer un serveur avant tous ses clients. b) La connaissance, par un client, du numéro de porte correspondant à un service, est une question de convention entre le client et le serveur.

    Création d'un serveur

    La commande

    dp_MakeRPCServer numero_de_porte
    crée un serveur, qui se met en attente d'une requête sur la porte indiquée. Si on donne 0 comme numéro de porte, le système choisira lui-même une porte libre. Dans tous les cas, la commande donne comme résultat le numéro de la porte réservée. Bien noter que le serveur exécute l'interprète dpwish et qu'il est donc capable de répondre à toute requête comprise par cet interprète (les commandes de Tcl-DP, et toute procédure déclarée dans le programme du serveur).

    Liaison d'un client

    La commande

    dp_MakeRPCClient machine numero_de_porte
    permet à un client d'obtenir une liaison vers un serveur défini par le couple (machine numero_de_porte).

    Le résultat de cette commande est l'identificateur d'une structure (le descripteur) qui permet désormais au client d'identifier le serveur (le contenu exact du descripteur est une information interne que le programmeur n'a pas besoin de connaître, et qui sert au fonctionnement des protocoles de communication). C'est cet descripteur qui devra être utilisé lors de l'appel proprement dit. Il faut donc le conserver dans une variable. On écrit donc en pratique :

    set serveur [dp_MakeRPCClient machine numero_de_porte]
    La variable Tcl serveur contient alors le descripteur du serveur.

    De la même façon, après le premier appel (voir ci-après), le descripteur du client deviendra connu chez le serveur. Dès lors, client et serveur jouent un rôle symétrique, chacun connaissant l'autre par un descripteur.

    Appel de procédure à distance

    Pour exécuter l'appel, le client doit fournir un descripteur de serveur (obtenu au préalable par dp_MakeRPCClient).
    L'appel est réalisé par la commande :

    dp_RPC $serveur commande
    serveur est une variable contenant le descripteur d'un serveur et commande est une commande Tcl. L'effet de l'appel est d'exécuter la commande commande et de renvoyer le résultat au client. Un autre effet est de mettre à jour chez le serveur une variable globale prédéfinie dp_rpcFile qui contient le descripteur du client.

    Note importante. Il faut bien distinguer l'environnement du client et l'environnement du serveur. En particulier :

    Exemple.

    Programme du serveur (serveur.tcl)
     

    dp_MakeRPCServer 4543;
    # ATTENTION, n'utilisez pas tous le même numero de porte!

    set compte 0;
    proc Suivant {} {

    global compte;
    # permet d'utiliser la variable compte du programme principal
    incr compte;
    return $compte;
    }

    Programme du client (client.tcl)

    set hote thales; # si le serveur a été lancé sur thales
    set porte 4543; # le numéro de porte du serveur
    set serveur [dp_MakeRPCClient $hote $porte] ;
    puts stdout "Ceci est l'appel numero ";
    puts stdout [dp_RPC $serveur Suivant];
    Remarque. Noter que ce service ne fait rien, sinon compter les appels qui lui sont faits. Il illustre néanmoins l'essentiel du fonctionnement de l'appel de procédure à distance. Essayer avec plusieurs clients.

    Exercice. Modifier ce programme pour que le serveur construise un tableau de tous les clients qui l'ont appelé, avec le nombre d'appels pour chaque client, et l'imprime tous les 10 appels.

    Suite du travail. Dans le répertoire

    /h/thales/u8/enseigt/krakowis/tp-tcl/Conference/
    vous trouverez trois fichiers (exemples fournis avec Tcl-DP) :
    LISEZ_MOI, room.tcl et enter.tcl
    Examinez ces fichiers, faites marcher le programme, et comprenez bien son fonctionnement.