1. L`architecture Java RMI • Les amorces (Stub et Skeleton

publicité
Université Kasdi Merbah Ouargla
Département Mathématique et informatique
1éme année Master informatique
Module ADIS &SAD
TP N°1
Avril 2012
1. L’architecture Java RMI
 Les amorces (Stub et Skeleton) : programmes jouant le rôle
d’adaptateurs pour le transport des appels distants (Skeleton n’est
pas nécessaire pour Java SDK). Ces amorces sont générées par le
compilateur des amorces : rmic
 La couche des références d’objets distants : permet d’obtenir la
référence d’un objet distant à partir de la référence locale Stub.
Page: 1
S.Euschi
C’est un service d’annuaire pour les objets distants enregistrés sur
le serveur. Lancée par le programme rmiregistry.
 La couche de transport : connecte les deux amorces (une souche de
la JVM client et une souche de la JVM serveur) en utilisant
TCP/IP.
2. Un exemple : l’écho distant
L’application serveur (interEcho.java et srvEcho.java)
Étape 1 : l’interface de l’objet sur le serveur (interEcho.java)
import java.rmi.*;
// l'interface distante
public interface interEcho extends Remote{
public String echo(String msg) throws java.rmi.RemoteException;
}
On déclare une interface interEcho déclarant une méthode echo comme accessible à distance.
Le traitement de l’exception utilise la classe RemoteException de java.rmi.
Étape 2 : écriture de l’objet serveur (srvEcho.java)
import java.rmi.*;
import java.rmi.server.*;
import java.net.*;
// classe implémentant l’écho distant
public class srvEcho extends UnicastRemoteObject implements interEcho{
// constructeur
public srvEcho() throws RemoteException{
super();
}// fin constructeur
// méthode réalisant l’écho
public String echo(String msg) throws RemoteException{
return "[" + msg + "]";
}// fin écho
// création du service
public static void main (String arg[]){
try{
srvEcho serveurEcho=new srvEcho();
Naming.rebind("srvEcho",serveurEcho);
System.out.println("Serveur d’écho prêt");
} catch (Exception e){
System.err.println(" Erreur " + e + " lors du lancement du serveur d’écho
");
}
}// main
}// fin classe
Page: 2
S.Euschi
Nous devons créer un objet de type srvEcho et l’enregistrer dans l’annuaire des objets
accessibles de l’extérieur. Cet enregistrement se fait avec la méthode rebind de la classe
Naming :
Naming.rebind(String nom, Remote obj)
avec
nom le nom qui sera associé à l’objet distant
obj l’objet distant
Dans l’exemple :
Naming.rebind("srvEcho",serveurEcho);
La classe srvEcho est dérivée de la classe UnicastRemoteObject, l’objet créé s’exécute
indéfiniment : il écoute les demandes des clients sur un port anonyme c’est à dire choisi par le
système selon les circonstances.
Étape 3 : compilation de l’application serveur
Javac interEcho.java, srvEcho.java
L’application client
Étape 4 : écriture du client (cltEcho.java)
On écrit un client à qui on passe en paramètre l’URL du serveur d’écho et qui
1. lit une ligne tapée au clavier
2. l’envoie au serveur d’écho
3. affiche la réponse que celui-ci envoie
4. reboucle en 1 et s’arrête lorsque la ligne tapée est « fin ».
import java.rmi.*;
import java.io.*;
public class cltEcho {
public static void main(String arg[]){
// syntaxe : cltEcho URLService
// vérification des arguments
if(arg.length!=1){
System.err.println("Syntaxe : pg url_service_rmi");
System.exit(1);
}
// dialogue client-serveur
String urlService=arg[0];
BufferedReader in=null;
String msg=null;
String reponse=null;
interEcho serveur=null;
try{
// ouverture du flux clavier
in=new BufferedReader(new InputStreamReader(System.in));
// localisation du service
serveur=(interEcho) Naming.lookup(urlService);
// boucle de lecture des msg à envoyer au serveur d'écho
System.out.print("Message : ");
msg=in.readLine().toLowerCase().trim();
while(! msg.equals("fin")){
// envoi du msg au serveur et réception de la réponse
reponse=serveur.echo(msg);
// suivi
System.out.println("Réponse serveur : " + reponse);
// msg suivant
System.out.print("Message : ");
Page: 3
S.Euschi
msg=in.readLine().toLowerCase().trim();
}// while
// c'est fini
System.exit(0);
// gestion des erreurs
} catch (Exception e){ import java.rmi.*;
import java.io.*;
public class cltEcho {
public static void main(String arg[]){
// syntaxe : cltEcho URLService
// vérification des arguments
if(arg.length!=1){
System.err.println("Syntaxe : pg url_service_rmi");
System.exit(1);
}
// dialogue client-serveur
String urlService=arg[0];
BufferedReader in=null;
String msg=null;
String reponse=null;
interEcho serveur=null;
try{
// ouverture du flux clavier
in=new BufferedReader(new InputStreamReader(System.in));
// localisation du service
serveur=(interEcho) Naming.lookup(urlService);
// boucle de lecture des msg à envoyer au serveur d'écho
System.out.print("Message : ");
msg=in.readLine().toLowerCase().trim();
while(! msg.equals("fin")){
// envoi du msg au serveur et réception de la réponse
reponse=serveur.echo(msg);
// suivi
System.out.println("Réponse serveur : " + reponse);
// msg suivant
System.out.print("Message : ");
msg=in.readLine().toLowerCase().trim();
}// while
// c'est fini
System.exit(0);
// gestion des erreurs
} catch (Exception e){
System.err.println("Erreur : " + e);
System.exit(2);
}// try
}// main
}// classe
L’instruction qui demande une référence de l’OD sur le serveur :
serveur=(interEcho) Naming.lookup(urlService);
La méthode lookup utilisée admet comme paramètre l’url du service demandé. Celle-ci a la
forme d’une url classique :
rmi://machine:port/nom_service
avec
rmi : facultatif - protocole rmi
machine : nom ou adresse IP de la machine sur laquelle opère le serveur d’écho facultatif, par défaut localhost.
Port : port d’écoute du service d’annuaire de cette machine - facultatif, par défaut 1099
nom_service nom sous lequel a été enregistré le service demandé (srvEcho pour notre
exemple)
Le client aura une instance de l’interface distante interEcho. Si on suppose que le client et le
serveur ne sont pas sur la même machine, lorsqu’on compile le client cltEcho.java, on doit
disposer dans le même répertoire, du fichier interEcho.class, résultat de la compilation de
l’interface distante interEcho, sinon on aura une erreur de compilation sur les lignes qui
référencent cette interface.
Page: 4
S.Euschi
interEcho..java (idem à celui du serveur)
import java.rmi.*;
// l'interface distante
public interface interEcho extends Remote{
public String echo(String msg) throws java.rmi.RemoteException;
}
Étape 5 : génération des fichiers .class nécessaires à l’application
client
Javac interEcho.java, cltEcho.java
Etape 6 : génération des amorces client et serveur
Au niveau du serveur et à partir de la classe srvEchi.class on va produire les classes :
srvEcho_Stub.class et srvEcho_Skel.class avec le compilateur rmic de java
rmic –vcompat srvEcho
On fait une copie du fichier srvEcho_stub.class dans le répertoire du client.
Étape 7: Exécution de l’application client-serveur d’écho
Sur le serveur on lance :
rmiregistry & (lancé en tache de fond dans une fenêtre DOS) ou start rmiregistry (préférable)
Dans une fenetre Dos on lance :
java srvEcho ou start java srvEcho (préférable)
Le serveur nous répond par :
Serveur d’écho prêt
Il ne nous reste plus qu’à lancer et tester notre client :
java cltEcho rmi://localhost/srvEcho
Le client distant utilise le service distant implémenté sur le serveur (une instance de l’objet
srvEcho qui implémente la méthode srvEcho.echo()) en envoyant des messages et le serveur
réalise l’echo de chaque message tant que le message envoyé par le client est différent de
« fin ».
Page: 5
S.Euschi
Exécution de l’exemple :
D:\exemple\serveur>start rmiregistry
D:\exemple\serveur>start java srvEcho
D:\exemple\client>java cltEcho rmi://localhost/srvEcho
Résultats :
Message : Bonjours
Réponse serveur : [Bonjours]
.
.
.
Message : fin
Page: 6
S.Euschi
Téléchargement