Master Informatique à Distance Communication dans les Systèmes Distribués Julien Bernard Année 2011–2012 Table des matières TD1 : La communication Exercice 1 : Première communication . . . . . . . . . . . . . . . . . . . Exercice 2 : Synchronisation de la communication . . . . . . . . . . . . Exercice 3 : Différentes problématiques de communication . . . . . . . 3 3 3 4 TD2 : Premiers pas avec les sockets Exercice 4 : Premières sockets . . . . . . Exercice 5 : Plusieurs échanges . . . . . Exercice 6 : Communication à plusieurs Exercice 7 : Taille des données inconnue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 6 7 7 8 TD3 : Sockets des experts Exercice 8 : Sans bibliothèque . . . . . . . . . . Exercice 9 : Bibliothèque de socket connectées . Exercice 10 : Synchronisation et blocages . . . Exercice 11 : Communication structurée . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 9 9 9 10 . . . . . . . . . . . . TD4 : Les sockets Java 11 Exercice 12 : Communication par buffeur . . . . . . . . . . . . . . . . 11 Exercice 13 : Communication objet . . . . . . . . . . . . . . . . . . . . 11 Exercice 14 : Communication Java-C . . . . . . . . . . . . . . . . . . . 11 TD5 : La programmation client/serveur avec sockets 13 Exercice 15 : Serveur concurrent de calcul . . . . . . . . . . . . . . . . 13 Exercice 16 : Serveur multi-services . . . . . . . . . . . . . . . . . . . . 13 TD6 : La programmation client/serveur avec sockets 15 Exercice 17 : Définition de protocole pour le serveur de calcul . . . . . 15 Exercice 18 : Serveur de numéros de port . . . . . . . . . . . . . . . . 15 TD7 : Développement et exécution d’applications RMI Exercice 19 : Application Hello distribuée . . . . . . . . . . . . . . . . Exercice 20 : Calcul distribué d’une approximation du nombre Pi . . . Exercice 21 : Encore une autre méthode d’approximation du nombre Pi 1 16 16 16 17 TD8 : Passage de paramètres dans les applications RMI 18 Exercice 22 : Boı̂te à messages électroniques . . . . . . . . . . . . . . . 18 TD9 : Téléchargement dynamique de classes et activation 20 Exercice 23 : Téléchargement dynamique de classes en RMI . . . . . . 20 Exercice 24 : Activation en RMI . . . . . . . . . . . . . . . . . . . . . 20 TD10 : Généralités sur CORBA 21 Exercice 25 : Questions du cours . . . . . . . . . . . . . . . . . . . . . 21 TD11 : Premières applications Exercice 26 : Hello . . . . . . . Exercice 27 : Horloge . . . . . . Exercice 28 : Boı̂te à messages CORBA 23 . . . . . . . . . . . . . . . . . . . . . . 23 . . . . . . . . . . . . . . . . . . . . . . 23 . . . . . . . . . . . . . . . . . . . . . . 24 TD12 : Types anonymes et invocations dynamiques en CORBA 25 Exercice 29 : Le type Any . . . . . . . . . . . . . . . . . . . . . . . . . 25 2 TD1 : La communication Exercice 1 : Première communication Les questions suivantes permettent d’illustrer de manière pratique la mise en place d’une communication. Il est donc nécessaire de recopier d’abord le code source pour pouvoir faire l’exercice. L’exécution ne peut se faire que sur une seule machine. Les fonctions envoyer et recevoir sont implantées sous la forme d’une bibliothèque. Question 1.1 Se placer dans le répertoire ex1/qu1, compiler les programmes (à l’aide de la commande make) et exécuter recepteur puis emetteur, dans deux fenêtres séparées. Question 1.2 Modifier les programmes recepteur et emetteur de manière à ce que recepteur retourne un message à emetteur. Question 1.3 Que se passe-t-il lorsque recepteur demande à recevoir deux fois puis envoie alors que emetteur envoie, puis reçoit et envoie ? Question 1.4 Que se passe-t-il lorsque recepteur et emetteur envoient en même temps puis reçoivent en même temps ? Exercice 2 : Synchronisation de la communication Le but de ces exercices est de comprendre comment sont mises en place les synchronisations entre les programmes communicants. 3 Question 2.1 Quel est le mode de synchronisation le plus adapté pour accéder à une base de données ? On peut envisager que l’émetteur donne le contenu de sa requête SQL dans un message et reçoit le résultat dans un autre message. Question 2.2 Quel est le mode de synchronisation le plus adapté pour envoyer un message publicitaire à un ensemble de destinataires ? Il est possible que la liste des destinataires ne soit pas à jour. Question 2.3 Quelles primitives de communication et quelle synchronisation utiliser pour permettre une mise au enchères ? Un programme principal tient le rôle de commissaire priseur auprès duquel des participants peuvent s’inscrire (il leur arrive d’oublier de se dés-inscrire) et faire des offres. Question 2.4 Quelles primitives de communication et quelle synchronisation utiliser pour développer un programme de jeux sur internet ? Les joueurs s’inscrivent et jouent des parties à plusieurs. On suppose qu’il est possible de savoir quand l’un des joueurs quitte le jeu et que chaque joueur doit jouer à son tour. Exercice 3 : Différentes problématiques de communication Le but de ces exercices est de réfléchir à différents problèmes posés par la communication. Question 3.1 D’après vos connaissance acquise en systèmes d’exploitation quel type d’identification est mis en place pour les fichiers locaux à une machine ? Comment est-il possible d’identifier des fichiers de l’ensemble des machines sur un réseau ? Question 3.2 Dans le programme de mise aux enchères précédent, quel mode de communication est le plus adapté : connecté ou non-connecté ? Et dans le cas du jeu ? 4 Question 3.3 Pour m’inscrire sur un site Internet, j’ai besoin de préciser mon nom, ma date de naissance et mon adresse. Si je ne dispose que de la fonction d’envoi du premier exercice, je ne peux envoyer qu’une chaı̂ne de caractère par envoi. Proposez un protocole d’échange entre deux programmes pour transmettre l’ensemble des informations nécessaires. Question 3.4 Dans la question précédente, proposer une solution pour transmettre toutes les données en une seule fois. Donner différents exemples de codage possibles. Proposer une solution dans le cas où les champs date de naissance et adresse sont optionnels. Question 3.5 Lorsque nous accédons à une base de données, il est particulièrement important d’avoir une garantie sur l’échange des messages. Quels sont les cas d’erreur possibles en analysant les différentes phases de la communication. Proposer une solution pour garantir l’accès à la base et le bon déroulement. 5 TD2 : Premiers pas avec les sockets Exercice 4 : Premières sockets Dans cet exercice nous allons utiliser les extraits de code vu en cours pour réaliser une première application avec des sockets. Positionnez vous dans le répertoire ex4/tmpl, il y a quatre fichers : client.c, serveur.c, emetteur.c, recepteur.c. Ils utilisent des fonctions simplifiées vu en cours qui se trouvent dans les fichiers fonctions/fonctionsSocket.h pour la déclaration et fonctions/fonctionsSocket.c pour la définition (nous vous conseillons de ne pas aller voir ce fichier dans un premier temps). Le Makefile vous montre comment compiler ces quatre programmes (qui ne font rien au départ). Pour exécuter les programmes, créez deux fenêtres shell, positionnez-vous dans le répertoire ex4/tmpl et lancez l’exécution de chacun des programmes dans des fenêtres différentes. En mode non-connecté, le programme récepteur doit être lancé en premier. En mode connecté, c’est le serveur qui doit être lancé en premier. Nous vous conseillons enfin d’utiliser localhost comme nom d’hôte. Question 4.1 Composer les parties de code données dans le cours pour passer une valeur entière entre deux sockets non-connectées et une chaı̂ne de caractère entre deux sockets connectées. Question 4.2 Faire l’inverse : la chaı̂ne en mode non-connecté puis la valeur en mode connecté. Question 4.3 Passer un tableau d’entiers entre deux programmes dans chacun des modes. 6 Question 4.4 Réaliser le passage des différents types de données : tableaux, structures et types définis par le programmeur. Exercice 5 : Plusieurs échanges Dans l’exercice précédent, nous nous sommes contentés de faire un échange entre les deux programmes. Dans cet exercice, nous mettons en place plusieurs échanges pour établir une vraie communication. Nous utilisons le mode connecté. Question 5.1 Compléter les progammes échangeant la chaı̂ne de caractères de manière à ce que le récepteur de la chaı̂ne retourne la taille de celle-ci à l’émetteur. Question 5.2 Écrire les programmes de manière à ce que l’émetteur de la chaı̂ne saisisse celle-ci au clavier avant de l’envoyer. Nous supposerons que la taille maximale de la chaı̂ne est de 256 caractères. Question 5.3 Modifier les programmes de manière à répéter l’échange tant que la chaı̂ne envoyée n’est pas fin. Dans ce cas, fermer proprement la connexion entre les deux programmes sans retourner de réponse. Question 5.4 Modifier le premier programme de l’exercice de manière à ce qu’il envoie successivement cinq chaı̂nes de caractères, sans attendre de retour du récepteur. Une fois les chaı̂nes reçues, le récepteur retourne un tableau contenant les différentes tailles des chaı̂nes. Exercice 6 : Communication à plusieurs Écrire trois programmes qui communiquent sous la forme d’un anneau : le premier envoie ses messages au deuxième, qui les envoie au troisième. C’est le premier programme qui initie la communication. Par la suite, un programme ne communique avec le suivant que s’il a reçu un message de son prédécesseur. Question 6.1 Quel mode de communication doit-on utiliser ? 7 Question 6.2 Comment garantir que les adresses utilisées pour les communications sont correctes si les programmes sont lancés par des personnes différentes sur des machines différentes ? Question 6.3 Comment permettre qu’aucun des programmes ne soit bloqué par les autres ? Question 6.4 Écrire les programmes. Exercice 7 : Taille des données inconnue Dans cet exercice, nous souhaitons mettre en place une communication avec des tailles de données inconnues. Utiliser les programmes en mode connecté réalisés à l’exercice Plusieurs échanges pour réaliser une communication où la taille de la chaı̂ne n’est pas fixée : Question 7.1 Quelle est l’incidence sur les programmes client et serveur ? Question 7.2 Proposer deux solutions différentes pour réaliser cet échange. Question 7.3 La solution est-elle différente si les programmes échangent un tableau d’entiers ? 8 TD3 : Sockets des experts Exercice 8 : Sans bibliothèque Question 8.1 Réécrire les programmes des exercices Premières sockets et Communication à plusieurs sans utiliser la bibliothèque fonctionsSocket, seulement avec les fonctions de l’interface socket standard. Exercice 9 : Bibliothèque de socket connectées Question 9.1 Écrire le code des fonctions socketClient et socketServeur qui permettent de créer de manière simple les sockets en mode connecté. Exercice 10 : Synchronisation et blocages Écrire un programme serveur et deux programmes clients de manière à ce que le serveur affiche le message du client qui envoie un message le premier. Question 10.1 Écrire les programmes en mode non-connecté, sans utiliser de fonctions nonbloquante ni la fonction select. Question 10.2 Écrire les programmes en mode connecté, sans utiliser de fonctions nonbloquante ni la fonction select. Question 10.3 Écrire les mêmes programmes avec des fonctions non-bloqantes puis avec la fonction select. Quels sont les avantages des deux méthodes ? 9 Exercice 11 : Communication structurée Écrire un programme serveur qui permet de réaliser les quatre opérations arithmétiques de base (+, −, ∗, /) pour le compte d’un client. Le serveur ne traite qu’un client qui envoie des opérations élémentaires : Question 11.1 Quel problème se pose pour la constitution d’un message et quelles solutions ? Proposer plusieurs solutions. Question 11.2 Écrire le programme serveur, puis le programme client. Question 11.3 Comment permettre à un client d’effectuer l’opération (4 ∗ 5) + (34/2) ? Question 11.4 Comment permettre à un client d’envoyer un nombre quelconque d’opérations à effectuer et de terminer sans affecter le serveur. Question 11.5 Quels sont les cas d’erreur possibles ? Apporter des solutions de manière à garantir la sécurité du serveur. Question 11.6 Le serveur traite plusieurs clients. Adapter le serveur pour qu’il soit accessible après la fin de l’exécution du programme client et serve un second client. Question 11.7 Le serveur traite plusieurs clients. Adapter le serveur pour qu’il puisse servir d’autres clients avant que le premier ne soit terminé. Proposer des solutions avec les sockets non-bloquantes et avec la fonction select. 10 TD4 : Les sockets Java Exercice 12 : Communication par buffeur Question 12.1 Écrire un programme qui permet l’envoi d’un buffer de caractères d’un client à un serveur. Le serveur retourne la taille du buffer lu. Exercice 13 : Communication objet On veut écrire deux programmes Java qui échangent un message composé de plusieurs informations : nom de l’émetteur, date d’émission et texte du message. Question 13.1 Comment réaliser cet échange de manière à ce que l’ensemble des données soient transmises en une seule fois ? Question 13.2 Comment structurer les fichiers de programmes de manière à permettre une évolution des données contenues dans le message ? Question 13.3 Écrire les programmes. Exercice 14 : Communication Java-C Il est possible de connecter des socket Java avec des sockets C. Cependant, le mode d’échange des données ne peut plus être à base d’objets. 11 Question 14.1 Comment réaliser un échange de plusieurs données de types différents entre les deux programmes ? Question 14.2 Écrire les programmes client et serveur. 12 TD5 : La programmation client/serveur avec sockets Exercice 15 : Serveur concurrent de calcul Reprendre l’exercice du serveur de calcul et utiliser un serveur concurrent : Question 15.1 Adapter le serveur pour qu’il puisse exécuter plusieurs opérations simultanément en créant dynamiquement des processus. Question 15.2 Adapter le serveur en utilisant un pool de processus. Question 15.3 Quels sont les avantages des différentes solutions ? Exercice 16 : Serveur multi-services Le processus xinetd (sous Linux, inetd sous UNIX SVR4 ou Solaris) permet de regrouper en un seul processus l’accès à différents services (daemons) pour éviter de lancer autant de processus que de services. Lorsque le processus reçoit une demande de connexion, il lance l’exécution du programme correspondant, par exemple : /usr/sbin/in.telnetd pour telnet ou /usr/sbin/rlogind pour rlogin. Chacun des services est accédé à travers son propre numéro de port, par exemple : ftp, port 21 ; telnet, port 23 ; time, port 37 ; etc. Question 16.1 Proposer un squelette d’implantation d’un processus xinetd. 13 Remarque La configuration du serveur xinetd (inetd sous Solaris) se fait dans le répertoire /etc/xinetd.d (le fichier inetd.conf sous Solaris). 14 TD6 : La programmation client/serveur avec sockets Exercice 17 : Définition de protocole pour le serveur de calcul Question 17.1 Reprendre le serveur de calcul et définir un protocole/interface à la manière de ce qui a été défini dans le cours. En particulier, il faut penser à définir correctement : les structures des requêtes, les structures des réponses, les codes des requêtes et les codes d’erreur. Exercice 18 : Serveur de numéros de port Le fichier /etc/services n’étant pas forcément le même sur toutes les machines, il serait utile de disposer d’un serveur centralisant toutes ces informations (à la manière du DNS pour les noms et les adresses IP des machines). Le serveur doit être capable de répondre aux requêtes de création et destruction d’un nouveau service (avec ou sans numéro de port fixé), de recherche du numéro de port d’un service ou de recherche d’un nom de service. Question 18.1 Proposer un protocole d’accès à ce serveur, donner le code du serveur et le code d’un client. 15 TD7 : Développement et exécution d’applications RMI Exercice 19 : Application Hello distribuée Question 19.1 Analyser et développer l’application Hello présentée en cours. Déployer l’application sur un environnement distribué. Exercice 20 : Calcul distribué d’une approximation du nombre Pi L’intérêt de cet exercice est de trouver une approximation du nombre π d’une manière distribuée. La formule la plus simple est celle déterminée par l’allemand Leibniz en 1674 : π 1 1 1 = 1 − + − + ··· 4 3 5 7 On supposera qu’un serveur dispose du savoir-faire pour calculer une approximation du nombre π à l’aide de cette méthode et les clients peuvent l’interroger afin de récupérer cette estimation. Question 20.1 Développer l’application distribuée permettant d’approximer la valeur du nombre π à partir de la formule de Leibniz. 16 Exercice 21 : Encore une autre méthode d’approximation du nombre Pi Sachez qu’aujourd’hui, il est connu 1 241 100 000 000 décimales de π ; c’est un japonais, Yasumasa Kanada, qui détient le record. Les méthodes d’approximation ont considérablement évolué. On ne s’intéresse pas à battre le record, mais à réaliser une comparaison entre des approximations de π calculées par deux méthodes : une qui calcule l’approximation à base de la formule de Leibniz, et une autre à base de la série Euler, définie de la manière suivante : ∞ X 1 ∗ 2 ∗ ··· ∗ n π = 2 1 ∗ 3 ∗ 5 ∗ · · · ∗ (2n + 1) n=0 Question 21.1 Développer un schéma d’application distribuée permettant, à partir d’un même ordre de développement des formules, de préciser laquelle des deux méthodes (Leibniz ou Euler), est plus exacte par rapport au référentiel donné par Java (Math.PI). 17 TD8 : Passage de paramètres dans les applications RMI Exercice 22 : Boı̂te à messages électroniques Nous souhaitons dans cet exercice réaliser une application permettant de gérer, à distance, une boı̂te à messages électroniques envoyés de la part de plusieurs clients. Le fonctionnement du serveur de boı̂te à messages est le suivant : – Avant tout dépôt de message de la part d’un client, le client doit s’inscrire auprès du serveur. Le serveur lui retourne un numéro unique qui lui permettra de s’identifier auprès du serveur lors de l’envoi des messages. – Un client accompagne le dépôt de son message du numéro d’inscription reçu de la part du serveur. Le message contient, à part le corps du message proprement dit, le nom du client et la date de l’envoi. – Le serveur accepte le dépôt d’un message d’un client, en conservant uniquement son dernier message déposé. – Un client peut consulter le message d’un client donné (lui-même ou un autre) : le serveur lui renvoie le dernier message du client ; un client est identifié par son numéro d’inscription. Question 22.1 Concevoir un schéma de mise en œuvre de la boı̂te à messages. Représenter sur un schéma les deux acteurs : le serveur et le client. Représenter par des flèches les invocations de méthodes mises en jeu lorsqu’un client souhaite envoyer un message au serveur de boı̂te à messages. Question 22.2 Écrire une classe Message qui contient le nom de l’émetteur, la date de l’envoi et un texte de message. 18 Question 22.3 Écrire un serveur de boı̂te à lettres pour qu’il permette l’inscription d’un client, l’envoi et la consultation des messages. Question 22.4 Supposons qu’un client qui vient d’envoyer un message se rend compte que la date du message est erronée. Il doit pouvoir modifier la date du message, mais sans le retransmettre. Est-il possible de le faire dans la solution actuelle ? Justifier votre réponse, et en cas négatif, proposer une solution. 19 TD9 : Téléchargement dynamique de classes et activation Exercice 23 : Téléchargement dynamique de classes en RMI Question 23.1 Déployer correctement l’application boı̂te à messages afin de tester le téléchargement dynamique de classes dans le mécanisme d’invocation distante RMI (voir section 7.5 du cours). Exercice 24 : Activation en RMI Une des approches utilisées pour rendre un objet accessible à distance est de l’exposer dans un serveur d’objets. Ce principe nécessite que la classe de l’implémentation de l’objet hérite la classe UnicastRemoteObject. Ce mécanisme a l’inconvénient d’utiliser en permanence les ressources du système. L’autre solution est de rendre l’objet distant activable, de créer l’objet distant dynamiquement, lorsqu’un client souhaite y accéder. Question 24.1 Modifier l’application RMI de boı̂te à messages afin d’utiliser le principe d’activation. 20 TD10 : Généralités sur CORBA Exercice 25 : Questions du cours Question 25.1 Qu’est ce que CORBA ? Question 25.2 Quels sont les principaux avantages de CORBA ? Question 25.3 Qu’est ce que l’interopérabilité dans CORBA ? Question 25.4 Comment définir un objet CORBA ? Question 25.5 Que trouve-t-on dans une IOR dans le protocole IIOP ? Question 25.6 Peut-on faire communiquer une application Java avec une application C++ en CORBA ? Si oui, pourquoi et comment ? Question 25.7 Quel est le rôle d’un contrat IDL ? 21 Question 25.8 Quel est le rôle d’un compilateur IDL ? 22 TD11 : Premières applications CORBA Exercice 26 : Hello Question 26.1 Écrire en CORBA une application permettant à un client de transmettre un message au serveur, qui l’affichera, sur son propre terminal, précédé par la chaı̂ne de caractères Hello . Deux versions seront analysées : – la diffusion de la référence de l’objet distant se fait par l’affichage de l’IOR de l’objet sur l’écran, lors de la création par le serveur ; – la diffusion de la référence de l’objet distant se fait par son enregistrement dans le service de nommage. Déployer les applications sur un environnement distribué – sans utilisation et avec utilisation du service de nommage. Exercice 27 : Horloge Le but de cet exercice est de proposer, dans une approche CORBA, un service de récupération de l’heure exacte, gérée par un serveur. Question 27.1 Développer une première version de l’application qui manipule le temps horloge sous la forme de trois attributs (heures, minutes, secondes). Écrire un contrat IDL équivalent qui offre trois opérations pour avoir accès aux informations d’un temps horloge. Écrire une autre variante qui permet d’obtenir le temps horloge grâce à l’appel d’un seul service. Question 27.2 Développer une deuxième version de l’application qui manipule le temps horloge sous la forme d’une structure de trois entiers. Deux solutions sont envisageables pour la récupération de l’heure de la part des clients : soit par un 23 retour de fonction, soit par un paramètre de type out. Proposer des solutions pour chacune des méthodes. Question 27.3 Développer une troisième version de l’application qui manipule le temps horloge sous la forme d’un tableau et ensuite d’une séquence. Exercice 28 : Boı̂te à messages Nous souhaitons dans cet exercice reprendre l’application de gestion d’une boı̂te à messages vue précédemment en RMI, afin de proposer une solution CORBA. Question 28.1 Définir le contrat IDL de l’application CORBA boı̂te à messages. Question 28.2 Définir l’implémentation de l’objet CORBA de gestion de la boı̂te à messages. Question 28.3 Définir les implémentations du serveur et des clients accédant aux services proposés par la boı̂te à messages. Question 28.4 Tester l’application CORBA en proposant un déploiement d’un serveur et de plusieurs clients. 24 TD12 : Types anonymes et invocations dynamiques en CORBA Exercice 29 : Le type Any On souhaite maintenant modifier l’application de boı̂te à messages pour qu’elle puisse contenir plusieurs sortes de message (texte, audio). Pour cela, on utilise le type générique IDL any qui permet de manipuler des valeurs de types quelconques. Votre nouvelle boı̂te doit respecter le contrat suivant : module b o i t e { struct Date { short annee , mois , j o u r ; short h , min , s e c ; }; struct TextMessage { s t r i n g nom ; Date dateMess ; s t r i n g mess ; }; struct AudioMessage { s t r i n g nom ; Date dateMess ; string a u d i o I n f o ; }; typedef sequence<any> L i s t e M e s s a g e s ; interface BoiteMessages { short i n s c r i r e ( ) ; void e n v o i e M e s s a g e ( in short c l i e n t , in any m) ; any g e t M e s s a g e ( in short c l i e n t ) ; }; }; 25 Question 29.1 Modifier votre implémentation de boı̂te pour respecter ce nouveau contrat. Question 29.2 Reprenez le serveur de l’exercice précédent. Écrire un client qui envoie un messages vers la boı̂te (d’un type donné) puis le récupère pour l’afficher. 26