Vous êtes sur la page 1sur 40

Chapitre IV

◼ Rappel des RPC (Remote Procedure Call)


⚫ modèle client/serveur
⚫ appel de procédures à distances entre un client et un serveur
• le client appelle une procédure
• le serveur exécute la procédure et renvoie le résultat
■ Limitations
• paramètres et valeur de retour sont des types primitifs
• programmation procédurale
• dépendance à la localisation du serveur
• pas d’ objet
• pas de « référence distante »

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

• Implémenter une interface signifie qu’il faut redéfinir toutes les


méthodes déclarées dans l’interface

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

▪ Convertir un montant de l’euro


▪ Envoyer au client la date du serveur

8
Règles d’usage:
➢ Interface

9
Règles d’usage:
➢ Implémentation

• Il faut maintenant implémenter l’interface distante dans


une classe. Par convention, le nom de cette classe aura pour suffixe Impl.

• Notre classe doit hériter de la classe java.rmi.server.RemoteObject ou


de l’une de ses sous-classes

• La plus facile à utiliser étant java.rmi.server.UnicastRemoteObject

• 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:

1. Définir un gestionnaire de sécurité (classe


RMISecurityManager):
• si le serveur est amené à charger des classes
System.setSecurityManager(new RMISecurityManager());

2. Créer les objets distants par instanciation de classes Remote:


MonObjetDistant Objet = new MonObjetDistant;

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

1. La première sera utilisée pour activer le registre. Pour cela,


vous devez exécuter l’utilitaire rmiregistry.

2. Dans une deuxième console, exécuter le serveur. Celui-ci va


charger l’implémentation en mémoire, enregistrer cette
référence dans le registre et attendre une connexion cliente.

3. Vous pouvez enfin exécuter le client dans une troisième


console
23
 génère les amorces (stub/skeleton)
◼ assurent le rôle d’adaptateurs pour le transport des appels
distants.
◼ Si l’implémentation est crée, les stubs et skeletons peuvent

être générés par l’utilitaire rmic en écrivant la commande


rmic NOM_IMPLEMENTATION
◼ réalisent les appels sur la couche réseau.

◼ réalisent l’emballage/déballage des paramètres (sérialisation ou

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

Vous aimerez peut-être aussi