2 Chap 4 RMI
2 Chap 4 RMI
2 Chap 4 RMI
2
Motivation : construction d’applications réparties avec Java
➢ Appel de méthode au lieu d’appel de procédure
Principe : même schéma que RPC
Le programmeur fournit:
Une (ou plusieurs) description(s) d’interface
Le programme du serveur
▪ Objets implémentant les interfaces
▪ Serveur d’objets
Le programme du client
L’environnement Java fournit: Un générateur de talons :
rmic et un service de noms : rmiregistry 3
Principes
■ RPC à la Java
• invoquer de façon simple des méthodes sur des objets distribués.
■ Mono-langage et Multiplateforme
• Java
■ Orienté Objet
■ Dynamique
• Les classes des souches et des paramètres peuvent être chargées
dynamiquement via HTTP (http://) ou NFS (file:/)
■ Sécurité
• un SecurityManager vérifie si certaines opérations sont autorisés par le serveur
4
Règles d’usage:
➢ Interface
• La première étape consiste à créer une interface distante qui décrit les
méthodes que le client pourra invoquer à distante
• Dans java, une interface est une classe abstraite qui ne contient
que des méthodes abstraites
5
Règles d’usage:
➢ Interface
L’interface d’un objet distant (Remote) est celle d’un objet Java, avec
quelques règles d’usage :
• L’interface distante doit être publique
• L’interface distante doit étendre l’interface « java.rmi.Remote »
• Chaque méthode doit déclarer au moins l’exception
« java.rmi.RemoteException »
Cette exception est levée :
- si connexion refusée à l’hôte distant
- ou bien si l’objet n’existe plus,
- ou encore s’il y a un problème lors de l’assemblage ou
le désassemblage. 6
Règles d’usage:
➢ Interface
// HelloInterface.java
// Définition d'interface
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface HelloInterface extends Remote
{
public String sayHello () throws RemoteException;
}
7
Règles d’usage:
➢ Interface
Supposant qu’on veut créer un serveur RMI qui crée un objet qui
offre les services distants suivant à un client RMI
8
Règles d’usage:
➢ Interface
9
Règles d’usage:
➢ Implémentation
• C’est dans cette classe que nous allons définir le corps des méthodes
distantes que pourront utiliser nos clients
10
Règles d’usage:
➢ Implémentation
11
Règles d’écriture du serveur:
Un serveur: classe qui implémente l’interface de l’objet
distant
➢ Spécifier les objets distants qui doivent être implémentées
➢ Définir le constructeur de l’objet distant
➢ Fournir l’implémentation des méthodes appelables à
distance
➢ Créer et installer le gestionnaire de sécurité
➢ Créer au moins une instance de la classe serveur
➢ Enregistrer au moins une instance dans le serveur de noms
12
Règles d’usage:
➢ Passage d’objets en paramètre
• Les objets locaux sont passés par valeur (copie) et doivent être
sèrialisables (étendent l’interface java.io.Serializable)
• Les objets distants sont passés par référence et sont désignés par leur
interface
13
Motivations
La sécurité est importante lorsqu’il y a téléchargement de code (il peut être
dangereux d’exécuter le code chargé depuis un site distant)
Installer un gestionnaire de sécurité
▪ Utile lorsqu’on télécharge du code à partir d’une machine
distante
▪ Permet de protéger la machine virtuelle java de tout utilisateur
malintentionné qui essaye de faire tourner du code malicieux
sur la machine.
Utiliser le gestionnaire de sécurité fournit par RMI:
RMISecurityManager
System.setSecurityManager(new RMISecurityManager()) 14
Le serveur doit enregistrer la référence de chaque objet
distant dans le service rmiregistry en attribuant un nom à cet
objet distant
Permet d’obtenir une référence d’objet distant
Utilise par défaut le port 1099
Accepte comme opérations l'enregistrement, l'effacement et
la consultation (méthodes de la classe java.rmi.Naming)
15
Classes utiles:
Naming : sert de représentant local du serveur de noms. Permet d’utiliser les méthodes
bind(), rebind(), lookup(), unbind(), list()
Méthode Action
Naming.bind void Naming.bind(String nom, Remote obj)
➢ associe l'objet au nom spécifié
Naming.rebind void Naming.rebind(String nom, Remote obj)
➢ réassocie le nom au nouvel objet
Naming.unbind void Naming.unbind(String nom)
➢ supprime l'enregistrement correspondant;
Naming.lookup Remote Naming.lookup(String nom)
➢ renvoie la référence de l'objet enregistré sous le nom
donné
Naming.list String[] Naming.list(String nom)
➢ renvoie la liste des noms enregistrés 16
17
Les opérations réalisées par le serveur:
18
3. Exposer les objets distants : rendre accessibles dans le
serveur
◼ Si la classe de l'objet a été définie comme une extension de
UnicastRemoteObject, l’exposition est automatique.
4. Faire connaitre l'existence des différents objets au serveur
de noms (rmiregistry) de la machine sur laquelle ce serveur
s'exécutera
Naming.rebind("nomUnObjet", unObjet);
19
Code du serveur RMI
20
• Le client peut obtenir une référence à un objet distant par
l’utilisation de la méthode statique lookup() de la classe
Naming
• La méthode lookup() sert au client pour interroger un
registre et récupérer un objet distant
• Elle retourne une référence à l’objet distant
• La valeur retournée est de type Remote. Il est donc
nécessaire de caster cet objet en l’interface distante
implémentée par l’objet distant
21
Code du client RMI
22
Il est maintenant possible de lancer l’application. Cela va
nécessiter l’utilisation de trois consoles
marshalling/unmarshalling).
◼ Une référence d’objets distant correspond à une référence
d’amorce (stub).
24
Le Stub (Souche) où partie client:
◼ représentant local de l’objet distant qui implémente les
méthodes visibles
◼ envoi des paramètres
◼ récupération des données
25
le Skeleton (Squelette) où partie Serveur:
◼ objet distant qui implémente les méthodes visibles
◼ réception des données
◼ exécution de la méthode
◼ envoi du résultat
26
1. Définir les spécifications du service RMI sous forme
d'interface (ProgInterface.java).
2. Créer l’implémentation de cette interface (ProgImp.java).
3. Compiler cette classe (javac ProgImp.java).
4. Créer une application serveur (AppServer.java).
5. Compiler l’application serveur.
6. Créer les classes pour le stub et le skeleton à l'aide de la
commande rmic
7. Lancer le serveur de noms avec rmiregistry.
27
8. Lancer le serveur AppServer pour la création d’objets et
leur enregistrement dans rmiregistry
9. Créer un programme client qui accède à des objets
distants (ProgClient.java).
10. Compiler et lancer ce programme client.
28
Invocation distante de la méthode multiplier( ) d’un objet
distant qui multiplie deux nombres réels fournis par
l’appelant.
29
import java.rmi.*;
public interface Service extends Remote {
public float multiplier(float a, float b) throws RemoteException;
}
30
import java.rmi.*;
import java.rmi.server.*;
public class ServiceImpl extends UnicastRemoteObject implements Service
{
public ServiceImpl() throws RemoteException {
super();
}
public float multiplier(float a, float b) throws RemoteException {
return a * b;
}}
31
import java.rmi.*;
public class ServiceServer {
public ServiceServer() {
System.setSecurityManager(new RMISecurityManager());
try {
ServiceImpl s=new ServiceImpl();
Naming.rebind(”rmi://localhost:1099/Service”, s);
} catch(Exception e) {
System.out.println(e.getMessage());
}
}
32
import java.rmi.*;
public class ServiceClient {
public static void main(String args[]) {
System.setSecurityManager(new RMISecurityManager());
try {
Service s=(Service) Naming.lookup(”rmi://localhost:1099/Service”);
System.out.println( s. multiplier (4.2f, 3.7f) );
} catch(Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
} 33
Invocation distante de la méthode reverseString()d’un
objet distant qui inverse une chaîne de caractères fournie
par l’appelant.
34
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface ReverseInterface extends Remote
{
String reverseString(String chaine) throws
RemoteException;
}
35
import java.rmi.*;
import java.rmi.server.*;
public class Reverse extends UnicastRemoteObject implements ReverseInterface {
public Reverse() throws RemoteException
{
super();
}
public String reverseString (String ChaineOrigine) throws RemoteException
{
StringBuilder sb = new StringBuilder();
// ajouter la chaîne dans StringBuilder
sb.append(ChaineOrigine);
sb = sb.reverse();
// afficher la chaîne inversée
return sb.toString();
} 36
import java.rmi.*;
public class ReverseServer{
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try{ System.out.println( "Serveur : Construction de l’implémentation ");
Reverse rev= new Reverse();
System.out.println("Objet Reverse lié dans le RMIregistry");
Naming.rebind("MyReverse", rev);
System.out.println("Attente des invocations des clients ...");
}
catch (Exception e) {
System.out.println("Erreur de liaison de l’objet Reverse");
System.out.println(e.toString()) }
}} 37
import java.rmi.*;
public class ReverseClient{
public static void main (String [] args) {
System.setSecurityManager(new RMISecurityManager());
try{
ReverseInterface rev= (ReverseInterface)
Naming.lookup("MyReverse");
String result= rev.reverseString(« rmi");
System.out.println("L’inverse est "+result);
}
catch (Exception e) {
System.out.println("Erreur d’accès à l’objet distant.");
System.out.println(e.toString());
}}} 38
▪ RMI:
◼ Accès à des objets distants
◼ Pas de langage séparé de description d’interfaces
▪ Limitations
◼ Environnement restreint à un langage unique (Java)
◼ Services réduits au minimum (Pas de services additionnels :
Duplication d’objets)
39
1. Olivier Glück, Architecture et communications Client/Serveur
-2018
2. «Réseaux», 4ième édition, Andrew Tanenbaum, Pearson
Education, ISBN 2-7440-7001-7
3. «La communication sous Unix», 2ième édition, Jean-Marie
Rifflet, Ediscience international, ISBN 2-84074-106-7
4. «Analyse structurée des réseaux», 2ième édition, J. Kurose et
K. Ross, Pearson Education, ISBN 2-7440-7000-9
5. Sacha Krakowia, Introduction aux objets répartis Java RMI,
2003-2004
40