Ecole Nationale des Sciences de l’Informatique
A. U. : 2014/2015
Devoir Surveillé Systèmes Répartis et Applications
Groupes Durée Responsables : F. Najjar&N. Ben Azzouna
: II2 --RSR&SLE : 2h00
: 11/03/2015
Date Documents : Non autorisés : 3 Nb. Pages
Prière de lire attentivement l’énoncé et de respecter les notations du texte. On demande des réponses brèves mais claires et précises.
Exercice1 : Questions diverses (6 points –2,5+0,5+2+0,5+0,5)
1) Dire par Vrai ou Faux et justifiez en cas de Faux (0,25 pour Vrai et 0,5 pour Faux) :
a) ________Le mécanisme de rpc peut appeler une procédure d’un processus localisé sur
une autre machine ?
b) ________Un programme utilisateur Sun RPC peut avoir n’importe quel numéro dans la
plage 0x10000000-0x3fffffff.
c) ________Sun RPC permet au développeur de spécifier le nom d’une interface.
d) ________L’utilitaire rpcgen génère une définition d’interface d’accès à une procédure
distante.
e) ________Un objet sérialisable peut être passé comme argument ou une valeur de
retour à un objet local.
f) ________Le rmiregistry est toujours sur le port 1099
g) ________Un « remoteobjectreference » est un identifiant unique d’objet dans les
systèmes distribués
2) Quels sont les objectifs principaux de l’utilisation d’un middleware dans un système
réparti (client/serveur)? En citez au moins deux.
3) Quelle est la différence fondamentale entre les paires de termes suivantes :
a) Serveur persistant et serveur stateful ?
b) portmapper et rpcbind ?
c) UnicastRemoteObject et Activatable ?
d) Classpath et Codebase
1
4) Que fait la commande
$ rpcinfo –u remoteHost 53687093 2
5) A quoi sert la version d’un programme rpc ?
Problème: Programmation par RPC(7 points— 1+2+1,5+1+1,5)
On souhaite développer une application client/serveur dans laquelle on offre les fonctions
suivantes :
unsignedinit_2rand (unsigneda, unsigned b), qui retourne un nombre
aléatoire compris entre aetb. On suppose quea <b.
unsignedget_next
(unsignedparam)
qui
retourne
la
valeur
de
paramincrémentée de 1.
1) Donnez le fichier Rand.x de spécification en RPCL.
2) Ecrire le code du serveur Rand_Server.c
3) Donnez la chaîne de production du serveur et dire comment peut-on vérifiez que ce
programme a bien été enregistré (en local) et qu’ilest bien fonctionnel?
4) Sans écrire totalement le programme Rand_Client.c dire comment un client se connecte au
serveur et effectue l’appel à distance de la fonction get_next(0x3fff)?. Et rappelez les
modules nécessaires à la génération du processus Rand_Client.
5) On souhaite modifier
le serveur afin qu’il puisse offrir
la nouvelle fonction
get_next(unsignedparam, unsigned pas), qui fait avancer la valeur du
paramètre param avec le pas passé.
a) Proposez une nouvelle spécification (optimale)rand.x.
b) Dire quelles sont les fonctions implémentées dans le serveur en donnant leur
prototype. Et puis, dire
comment un
client peut
faire
appel
à
get_next(init_2rand(1,5000),5) ?
6) (optionnelle 0,5 point) Quelle est la fonction de déconnexion dans l’application Client.
BON TRAVAIL
2
Proposition de correction
DS II2-SAR 11/03/2105
Exercice1 : Questions diverses (6 points –2,5+0,5+2+0,5+0,5)
Publicité
1) Dire par Vrai ou Faux et justifiez en cas de Faux (0,25 pour Vrai et 0,5 pour Faux) :
a) ___Vrai __Le mécanisme de rpc peut appeler une procédure d’un processus localisé
sur une autre machine ?
//0,25 pt
b) __Faux__Un programme utilisateur Sun RPC peut avoir n’importe quel numéro dans
la plage 0x10000000-0x3fffffff.
//0,5 pt
Plage publique dans 0x20000000-0x3fffffff
c) Vrai _Sun RPC permet au développeur de spécifier le nom d’une interface.//0,25 pt
d) __Faux_L’utilitaire rpcgen génère une définition d’interface d’accès à une procédure
distante.
e) Génération de code stub et skeleton, en plus de l’entête
//0,5 pt
f) __Vrai ___Un objet sérialisable peut être passé comme argument ou une valeur de
retour à un objet local.
//0,25 pt
g) ___Faux__Le rmiregistry est toujours sur le port 1099
Par défaut sur le port 1099 mais peut être modifié
//0,5 pt
h) __Vrai __Un « remoteobjectreference » est un identifiant unique d’objet dans les
systèmes distribués
//0,25 pt
2) Quels sont les objectifs principaux de l’utilisation d’un middleware dans un système réparti
(client/serveur)? En citez au moins deux.
Faciliter la conception, le développement et le déploiement d’applications
reparties (API), Masquer l’hétérogénéité de l’infrastructure sous-
jacente, Fournir des services communs (tq. Services de nommage, de
transaction, de sécurité, …)
// 0,5 point
3) Quelle est la différence fondamentale entre les paires de termes suivantes :
3
e) Serveur persistant et serveur stateful ? serveur persistant concerne le
stockage des données manipulées par
le serveur
sur
les
différentes requêtes de clients et serveur stateful concerne les
donnees enregistrees sur le client.
// 0,5 point
f) portmapper et rpcbind ? rpcbind est le successeur du service de
nommage portmapper
// 0,5 point
g) UnicastRemoteObject et Activatable ? la classe UnicastRemoteObject
permet d’activer explicitement l’OD alors que la classe Activable
permet une activation implicite via le demon rmi
// 0,5 point
h) Classpath et Codebase Classpath et codebase sont toutes les deux
des variables d’environnement permettant de retrouver les classes
java. Classpath s’utilise en local alors que codebase permet de
retrouver à distance les classes telles que les stubs, …//0,5 point
4) Que fait la commande
$ rpcinfo –u remoteHost 53687093 2
Appelle la procédure 0 du programme numéro 53687093 avec la version 2
sur la machine remotehost. Genre de ping afin de vérifier le bon
fonctionnement du réseau et que le serveur est opérationnel.
//0,5 point
5) A quoi sert la version d’un programme rpc ? maintenir l’indépendance entre le
client et le serveur
// 0,5 point
Exercice 2: Programmation par RPC (7 points— 1+2+1,5+1+1,5)
1) Donnez le fichier Rand.x de spécification en RPCL.
//fichier Rand.x
struct par1 {
// 0,25 point
unsignedinf ; unsigned sup ; };
typedefstruct par1 Par1;
4
program RANDOM_PROG {
// 0,75 point
version VERS_UN {
void RAND_NULL(null) = 0; //procedure de test //optionnelle unsigned init_2rand(Par1 p) = 1; unsignedget_next(unsigned par) = 2;
} =1; } = 0x23456781;
2) Ecrire le code du serveur Rand_Server.c
Publicité
#include”Rand.h”
// 0,25 point
void * RAND_NULL_1_svc(void *argp, structsvc_req *rqstp) {
static char * result; printf ("Success Ping\n"); fflush (stdout); return (void *) &result;
}
unsigned *init_2rand_1_svc(Par1 *argp, structsvc_req *rqstp) { // 1 point
static Par1 result ;
// On suppose argp->inf<argp->sup
result = rand()% (argp->sup - argp->inf) + argp->inf
return&result;
} unsigned *get_next_1_svc(unsigned *argp, structsvc_req *rqstp) {// 0,75 point
static unsigned result ;
result =*argp ++;
return&result;
}
3) Donnez la chaîne de production du serveur et dire comment peut-on vérifiez que ce programme a
bien été enregistré (en local) et qu’ilest bien fonctionnel?// 0,25/ligne réponse
rpcgenRand.x
gcc –o serveur Rand_Server.cRand_svc.cRand_xdr.c
gcc –o client Rand_Client.cRand_clnt.cRand_xdr.c
5
./serveur &
rpcinfo –p localhost(vérifier qu’il est bien enregistré et récupérer le num_prog) et
puis,
rpcinfo –u localhostnum_prog(vérifier qu’il est bien fonctionnel)
4) Sans écrire totalement le programme Rand_Client.c dire comment un client se connecte au serveur et
effectue l’appel à distance de la fonction get_next(0x3fff)?. Et rappelez les modules
nécessaires à la génération du processus Rand_Client.
// 0,25 déclaration #include ‘’Rand.h’’ CLIENT *clnt; unsigned result;
// 0,25 création clnt = clnt_create (host, RANDOM_PROG, VERS_UN, "TCP"); ……… // 0,5création result = get_next_1(&0x3fff, clnt) ; ………
5) On
souhaite modifier
le
serveur
afin qu’il puisse offrir
la nouvelle
fonction
get_next(unsignedparam, unsigned pas), qui fait avancer la valeur du paramètre
param avec le pas passé.
a)
Proposez une nouvelle spécification (optimale) rand.x.
struct par1 { Unsigned inf ; Unsigned sup ; ; typedefstruct par1 Par1;
// 0,25point struct par2 { unsignedparam ; unsigned pas ; ; typedefstruct par2 Par2;
program RANDOM_PROG { version VERS_UN {
void RAND_NULL(null) = 0; //procedure de test //optionnelle unsigned init_2rand(Par1 p) = 1; unsignedget_next(unsigned par) = 2;
6
} =1;
// 0,5point version VERS_DEUX {
void RAND_NULL(null) = 0; //procedure de test //optionnelle unsigned init_2rand(Par1 p) = 1; unsignedget_next(Par2 par) = 2;
} =2;
} = 0x23456781;
b) Dire quelles sont les fonctions implémentées dans le serveur en donnant leur prototype. Et puis, dire comment un client peut faire appel à get_next(init_2rand(1,5000),5) ?
//------- chez le client CLIENT *clnt; Par1 borne ; Par2 nb ; unsigned result ;
……… // 0,25point clnt = clnt_create (host, RANDOM_PROG, VERS_DEUX, "TCP");
……… borne.inf=1 ; borne.sup=5000 ;
nb.param = init_2rand_2(borne, clnt) ;
// 0,25 point
nb.pas =5;
result = get_next_2(&nb, clnt)
// 0,25 point
………
7) (optionnelle 0,5 point) Quelle est la fonction de déconnexion dans l’application Client.
Clnt_destroy(clnt) ;
Exercice 3 : Programmation RMI (7 points— 1+1+1+1+1,5+1,5)
On propose le code incomplet de l’interface et des classes suivantes :
public class Hello { public void hello() { System.out.println("Hello.hello()"); }}
7
public interface IBonjour { public void bonjour(); }
public class Bonjour implements IBonjour { public Bonjour(){ } public void bonjour(){ System.out.println("Bonjour.bonjour()"); }}
1) Complétez le code de IBonjour pour qu’elle soit une interface distante et celui de
Bonjour pour qu’il soit celui d’un objet distant temporaire qui sera ramassé par le DGC
à la fin de son exécution.
Pour IBonjour il faut ajouter
Publicité
extends java.rmi.Remote //0,25
throws java.rmi.RemoteException pour bonjour() //0,25 à condition qu’elle soit ajoutée
aussi à bonjour dans Bonjour
Pour Bonjour, il faut ajouter
,Unreferenced après IBonjour //0,25
public void unreferenced(){ //0,25
try{ ThreadGroup tg = Thread.currentThread().getThreadGroup(); tg.destroy(); } catch(Exception e) { System.out.println (e.toString()); } } Le code de unreferenced n’est pas obligatoire il faut juste indiquer qu’il faut ajouter cette méthode. throws java.rmi.RemoteException pour la méthode bonjour
2) Comment doit être l’objet Hello pour qu’on puisse le transférer à travers le réseau ?
Complétez le code de la classe Hello pour ce faire.
Hello doit être serializable //0,5 : implements java.io.Serializable //0,5 si on ne met pas
java.io où on ne fait pas import java.io mettre 0,25 uniquement
L’objet Bienvenue implémente une interface distante IBienvenue qui possède quatre
méthodes :
void direHello(Hello h) qui invoque la méthode hello de Hello,
void direBonjour(IBonjour b) qui invoque la méthode bonjour de
Bonjour,
Hello newHello() qui retourne un objet Hello,
8
IBonjour newBonjour() qui retourne une référence sur un objet
Bonjour.
3) Le client appelle la méthode newHello, puis la méthode direHello sur le résultat de
newHello (i.e., un appel de la forme s.newHello().direHello(), où s désigne
une variable de type IBienvenue contenant une référence vers l'objet serveur distant):
par quelle JVM la méthode direHello est-elle exécutée ? Justifiez.
Ici normalement newHello va rendre une instance de Hello par valeur au client qu’il va
passer en paramètre à direHello (donc par valeur) donc l’exécution sera faite par la
JVM du serveur sur la copie passée mais ici dans l’énoncé ce qui est entre parenthèse()
est faux : il correspond plutôt à la façon d’appeler hello() de Hello donc si l’étudiant
considère ce cas là l’exécution sera faite par la JVM du client.
//La note sera attribuée selon l’explication fournie, 0 si pas de justification.
4) Le client appelle la méthode newBonjour, puis la méthode bonjour sur le résultat de
newBonjour (i.e., un appel de la forme s.newBonjour().bonjour(), où s désigne
une variable de type IBienvenue contenant une référence vers l'objet serveur distant) :
par quelle JVM la méthode bonjour est-elle exécutée ? Justifiez.
newBonjour renvoie une référence sur l’objet Bonjour qui sera créé côté
serveur. L’appel de la méthode bonjour va s’exécuter donc sur la JVM
Serveur.
// 0 si pas de justification.
5) Ecrivez le code d’un client qui :
a) récupère une référence sur un objet Bienvenue enregistré sous le nom
MonBienvenue dans le rmiregistry, supposé déjà lancé sur le port 1099 ;
b) crée une instance d’un objet Hello et d’un objet Bonjour grâce aux
méthodes newHello et newBonjour de
l’objet distant et appelle
respectivement les méthodes hello et bonjour de ces objets comme
expliqué dans les questions précédentes.
import java.rmi.Naming; //0,25 pour le import
public class BienvenueClient { public static void main(String args[]) {//0,25
try { //0,25 pour le try catch // Récupuration d'un stub sur l'objet serveur.
9
IBienvenue obj = (IBienvenue) Naming.lookup("rmi://localhost/MonBienvenue");//0,5 // on doit pas oublier le cast + bonne URL obj.newBonjour().bonjour();//0,25 obj.newHello().hello() ;
} catch (Exception e) {
System.out.println("BienvenueClient err: " + e.getMessage()); e.printStackTrace(); } } }
6) Sans chargement dynamique, quelles sont les classes qui doivent exister dans le
CLASSPATH du client pour qu’il puisse s’exécuter ? Justifiez.
BienvenueClient.class : code du client //0,25
IBienvenue.class, Bienvenue_stub.class : pour
invoquer newBonjour() et
newHello() à distance et faire lookup(). //0,5
IBonjour.class, Bonjour_stub.class : pour invoquer bonjour() //0,5
Hello.class : pour invoquer hello() //0,25
//0 si pas de justification.
10