Académique Documents
Professionnel Documents
Culture Documents
…>>
Cours "Réseaux et systèmes répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 1
Définitions
RMI = Remote Method Invocation
RMI est une solution pure Java permettant de réaliser l’invocation à
distance de méthode d’objet
Elle est accessible à travers les classes et interfaces prédéfinies d’API
Java
Ces API sont :
java.rmi
java.rmi.server
java.rmi.registry
Ainsi, les composants de l’orb RMI sont :
Les API
Le compilateur IDL
L’annuaire ou adaptateur
Les descriptions des API qui suivent sont volontairement incomplètes afin de décrire l’essentiel.
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 2
Les API : java.rmi.*
class Naming
Cette classe gère le service de nommage
static void bind(String name, Remote obj)
Binds the specified name to a remote object.
static String[] list(String name)
Returns an array of the names bound in the registry.
static Remote lookup(String name)
Returns a reference, a stub, for the remote object associated with the
specified name.
static void rebind(String name, Remote obj)
Rebinds the specified name to a new remote object.
static void unbind(String name)
Destroys the binding for the specified name that is associated with a
remote object.
class RMISecurityManager
Cette classe gère les autorisations d'utilisation de Java pour RMI
System.setSecurityManager(new RMISecurityManager());
Interface Remote
Utilisé dans les interfaces (IDL)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 3
Exemple de RMISecurityManager
Les RMIs propose un gestionnaire de sécurité RMISecurityManager qui
par défaut interdit tout ce qu'un SecurityManager peut interdire, sauf la
définition de classe.
classe Pour permettre plus de chose il faut écrire son propre
gestionnaire de sécurité héritant de RMISecurityManager .
Exemple d'un serveur de calcul de complexe ou toutes les classes sont
chargées dynamiquement par le client.
package test.rmi;
import java.rmi.*;
import java.util.*;
public class ComplexCompute {
public static void main(String [] args) throws Exception {
Properties p=System.getProperties();
p.put("java.rmi.server.codebase","http://xxxx.fr/compte/CLASSES");
System.setProperties(p);
System.setSecurityManager(new RMISecurityManager());
ComplexOps obj = (ComplexOps) Naming.lookup("//"+ args[0]+
":10003/ComplexOps");
Complex c1 = obj.newComplex(1,1);
Complex c2 = obj.newComplex(2,2);
Complex c3 = obj.addComplex(c1,c2);
Complex c4 = obj.multComplex(c1,c2);
System.out.println(c1 + " + " + c2 + " = " + c3);
System.out.println(c1 + " * " + c2 + " = " + c4);
} }
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 4
Les API : java.rmi.server.*
class UnicastRemoteObject
Cette classe gère tout ce qui concerne un "servant" pour RMI
protected UnicastRemoteObject()
Creates and exports a new UnicastRemoteObject object using an anonymous port.
protected UnicastRemoteObject(int port)
Creates and exports a new UnicastRemoteObject object using the particular
supplied port.
protected UnicastRemoteObject(int port, RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
Creates and exports a new UnicastRemoteObject object using the particular
supplied port and socket factories.
static RemoteStub exportObject(Remote obj)
Exports the remote object to make it available to receive incoming calls using an
anonymous port.
static Remote exportObject(Remote obj, int port)
Exports the remote object to make it available to receive incoming calls, using the
particular supplied port.
static Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
Exports the remote object to make it available to receive incoming calls, using a
transport specified by the given socket factory.
static boolean unexportObject(Remote obj, boolean force)
Removes the remote object, obj, from the RMI runtime.
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 5
Deux façons de créer un objet distribué
par héritage : via les constructeur de UnicastRemoteObejct (voir
l'exemple RMI)
par agrégation : via la méthode exportObject (voir l'exemple RMI)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 6
Les API : java.rmi.registry (1/2)
class LocateRegistry
Cette classe gère en local d'un "serveur" le service de nommage
static Registry createRegistry(int port)
Creates and exports a Registry on the local host that accepts requests on the
specified port.
static Registry createRegistry(int port, RMIClientSocketFactory csf,
RMIServerSocketFactory ssf)
Creates and exports a Registry on the local host that uses custom socket factories
for communication with that registry.
static Registry getRegistry()
Returns a reference to the the remote object Registry for the local host on the
default registry port of 1099.
static Registry getRegistry(int port)
Returns a reference to the the remote object Registry for the local host on the
specified port.
static Registry getRegistry(String host)
Returns a reference to the remote object Registry on the specified host on the
default registry port of 1099.
static Registry getRegistry(String host, int port)
Returns a reference to the remote object Registry on the specified host
port.static Registry getRegistry(String host, int port, RMIClientSocketFactory csf)
Returns a locally created remote reference to the remote object Registry on the
specified host and port.
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 7
Les API : java.rmi.registry (2/2)
Interface Registry
Cette interface permet de créer une autre implémentation du service de
nommage
void bind(String name, Remote obj)
Binds a remote reference to the specified name in this registry.
String[] list()
Returns an array of the names bound in this registry.
Remotelookup(String name)
Returns the remote reference bound to the specified name in this
registry.
Void rebind(String name, Remote obj)
Replaces the binding for the specified name in this registry with the
supplied remote reference.
Void unbind(String name)
Removes the binding for the specified
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 8
Les packages de javax
javax.rmi
javax.rmi.CORBA
Ces deux packages contiennent tous les éléments permettant de mettre
en œuvre RMI-IIOP (AD)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 9
Le compilateur IDL
En RMI, le compilateur IDL est une fourniture du JDK java que l’on trouve
dans le répertoire bin (exemple sur le JEE 1.5 : C:\Sun\AppServer\jdk\bin)
Il est donc accessible via le PATH
La syntaxe : rmic <package>.<nom classe OD>
La commande rmic permet de générer les squelettes (skelton) et les
amorces (stub) RMI.
<nom classe OD> est le nom de la classe de l’OD (qui hérite de
UnicastRemoteObjetct et surtout hérite d’une interface dans laquelle sont
décrites les méthodes distantes de l’OD
Il est à noter que depuis la version 1.5, il est inutile d’utiliser la commande
rmic car java prend en charge nativement et dynamiquement la création
des objets de classes Stub et Skeleton.
Nous verrons que en RMI-IIOP, il est indispensable d’utiliser la
commande rmic (rmic –iiop …)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 10
L’adaptateur d’objet (1/2)
Il existe 3 façons d'exécuter un adaptateur RMI :
en utilisant la classe prédéfinie sun.rmi.registry.RegistryImpl
exemple: java -classpath "packages" sun.rmi.registry.RegistryImpl 9999
avantages : un meilleur pilotage du classpath, se lance à l'extérieur
inconvénients : doit toujours être lancé avant tous les autres programmes serveur,
peut être obsolète (confusion avec java.rmi.registry.RegistryImpl), le port est un
paramètre de commande OS
en utilisant la commande rmiRegistry (c'est un exe qui utilise le $CLASSPATH)
exemple: rmiRegistry 9999
avantages : façon récente d'exécuter un adaptateur à l'extérieur
inconvénients : pas de pilotage du classpath, variable d'environnement, le port est
un paramètre de commande OS
en créant l'adaptateur dans le code (le classpath de la JVM)
exemple : try {LocateRegistry.createRegistry(9999);}
catch(Exception l_ex){};
avantages : intégrer au code, le port peut être précisé par configuration (fichier,
properties, …),
inconvénients : intégrer au code, fonction du classpath de la JVM, nécessite un
programme serveur maître devant être exécuté avant tous les autres
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 11
L’adaptateur d’objet (2/2)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 12
Le Socket Factory RMI (1/4)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 13
Le Socket Factory RMI (2/4)
super()
les ports sont alloués par le système automatiquement
pas de politique ciblé de sécurité
Un seul serveur de socket par JVM
bi
bi
bi
nd
n
n
d
d
bi
nd
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 14
Le Socket Factory RMI (3/4)
super(port)
les ports sont déterminés par l'administrateur
politique ciblé de sécurité
Autant de serveur de socket que de port différent
Attention au conflit de port pour une même machine
bi
bi
nd
bin
bi
nd
nd
d
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 15
Il semble que le schéma décrit la politique suivante :
dans la JVM1 tous les objets distribués s'exécutent sur le même port
(9101)
dans la JVM2 chaque objet distribué s'exécute sur un port dfférent.
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 16
Le Socket Factory RMI (4/4)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 17
Création d'un objet distribué en RMI
deux façons :
par héritage
par construction
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 18
Mise en œuvre RMI (1/5)
Description dynamique de la mise en œuvre RMI des composants
logiciels du serveur
rmiregistry
9105
NOM_OD
Naming Naming
3 NOM_OD
1
Client
Serveur
2
Stub 2 2
Sekelton
9105
JVM Client JVM Serveur
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 19
Mise en œuvre RMI (2/5)
1 - L'objet serveur s'enregistre auprès du Naming de sa machine
(méthode rebind)
2 - L ’objet skeleton est créé par le Naming, il crée le port de
communication et maintient une référence vers l'objet serveur
3 - Le Naming enregistre l'objet serveur, et le port de communication
utilisé dans du serveur de noms
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 20
Mise en œuvre RMI (3/5)
Description dynamique de la mise en œuvre RMI des composants
logiciels du client
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 21
Mise en œuvre RMI (4/5)
4 - L'objet client fait appel au Naming pour localiser l'objet serveur
(méthode lookup)
5 - Le Naming récupère les "références" de l'objet serveur, ...
6 - crée l’objet Stub et ...
7 - rend sa référence au client
8 - Le client effectue l'appel au serveur par appel à l’objet Stub
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 22
Mise en œuvre RMI (5/5)
Le client effectue l'appel au serveur par appel à l’objet Stub
rmiregistry
9105
NOM_OD
Naming Naming
Client
Serveur
8 8
Stub 8
Sekelton
9105
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 23
Exemple RMI : Description
Cet exemple correspond en la création d'un seul objet distribué, nommé
HELLO, utilisé par deux clients en parallèle
Il encapsule un objet métier, un Individu composé d'un nom et d'un
prénom
Deux approches fonctionnelles côté serveur :
(cas A) l'objet distribué permet les services suivants :
obtenir un texte de bienvenu correspondant à l'individu en question
changer l'identité de la personne
(cas B) l'objet distribué permet le get et set sur l'Individu
Deux approches fonctionnelles côté client :
en correspondance avec le cas A :
le client 1 demande le texte de bienvenu et l'affiche
le client 2 change l'identité de l'individu
en correspondance avec le cas B :
le client 1 demande l'individu, construit le texte de bienvenu et l'affiche
le client 2 change l'individu
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 24
Exemple RMI : Architecture (cas A)
Le client 1 demande un service au serveur qui réalise le service demandé
Le traitement se fait côté serveur
On est dans un cas "orienté service"
Les clients n'ont pas de copie des objets encapsulés
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 25
Exemple RMI : Architecture (cas B)
Le client 1 demande le contenu de l'objet et en reçoit une copie
Le traitement se fait côté client
On est dans un cas "orienté objet"
Les clients récupèrent une copie de l'objet encapsulé par le serveur
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 26
Exemple RMI : Commentaires (1/2)
Le code est disponible sur le site (réf: NFP214_Exemple_009_ExempleRMI)
Le serveur :
deux scripts pour l'exécuter :
runServeur.bat : l'adaptateur doit être exécuter avant
runServeurEtRegistre.bat : l'adaptateur est exécuter par le serveur.
le programme principal : ExempleRmi.java
crée et exécute l'adaptateur en fonction d'un paramètre
crée l'objet distribué comme un objet quelconque
enregistre l'OD dans l'adaptateur se trouvant au port 9999
l'objet distribué : HelloOD.java
hérite de UnicatRemoteObject
implémente les méthodes distantes de l'interface HelloODInt
encapsule un objet Individu
l'objet Individu
objet quelconque
implémente Serializable pour pouvoir être échangé (cas B) entre le serveur et le
client (inutile dans le cas A)
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 27
Exemple RMI : Commentaires (2/2)
Cas 1, Client 1 :
lookup : connexion sur l'OD
appel à la méthode distante hello() qui retourne la phrase de bienvenue
construite par l'OD
affiche sa valeur si cette dernière change sur le serveur
Cas 1, Client 2 :
lookup : connexion sur l'OD
appel à la méthode distante setIdent(nom,prenom) afin de changer les valeurs
sur l'OD
Cas 2, Client 1 :
lookup : connexion sur l'OD
appel à la méthode distante getIndividu() qui retourne l'individu de l'OD
le client fabrique la phrase de bienvenue
affiche la chaîne si l'individu sur le serveur à changé
ATTENTION: il faut implémenter la méthode equals de la classe Individu
Cas 2, Client 2 :
lookup : connexion sur l'OD
appel à la méthode distante setIndividu() pour changer l'individu.
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 28
Exemple RMI : Le programme principal (serveur)
public class ExempleRMI
{
public static void main(String args[]) throws Exception
{
if (args.length == 1)
{
if (args[0].equals("registre"))
{
LocateRegistry.createRegistry(9999);
}
}
System.out.println("Bus en ecoute....");
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 29
public class HelloOD extends UnicastRemoteObject implements
Exemple RMI : L'OD HelloODInt
{
private Individu individu;
// POUR LE CAS B
// =============
public Individu getIndividu() throws RemoteException;
public void setIndividu(Individu a_individu) throws
RemoteException;
}
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 31
Exemple RMI : L'objet
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 32
Exemple RMI : Les clients du cas A
public class CasA_Client1
{
public static void main(String args[]) throws Exception
{
HelloODInt helloServices =
(HelloODInt)(Naming.lookup("rmi://localhost:9999/HELLO"));
while(true)
{
if (message.equals(messageOld)==false)
{
System.out.println(message);
messageOld = message;
}
message = helloServices.hello();
}
}
} public class CasA_Client2
{
public static void main(String args[]) throws Exception
{
HelloODInt helloServices =
(HelloODInt)(Naming.lookup("rmi://localhost:9999/HELLO"));
helloServices.setIdent(args[0],args[1]);
}
}
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 33
Exemple RMI : Les clients du cas B
public class CasB_Client1
{
public static void main(String args[]) throws Exception
{
HelloODInt helloObjet =
(HelloODInt)(Naming.lookup("rmi://localhost:9999/HELLO"));
while(true)
{
if (l_individu.equals(l_individuOld)==false)
{
String message = "BONJOUR : " +
l_individu.getNom() + l_individu.getPrenom();
System.out.println(message);
l_individuOld = l_individu;
}
l_individu = helloObjet.getIndividu();
}
} public class CasB_Client2
} {
public static void main(String args[]) throws Exception
{
HelloODInt helloObjet =
(HelloODInt)(Naming.lookup("rmi://localhost:9999/HELLO"));
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 35
L'atelier 6 : La conversion d'une devise
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 36
L'atelier 6 : cas 1 (2/2)
Prenons un cas fonctionnel: la conversion d'une devise.
Une devise est définit par 2 noms de monnaies et le taux permettant de
passer de la première à la deuxième.
La devise est donc une classe Devise.java.
Le service du serveur est de retourner au client un objet devise avec
lequel il peut faire ses conversions.
Cet objet devise est créé dans l'interface et n'est pas connu du serveur.
Cette solution est correcte. Le client ne peut pas changer le taux
(private). L'objet devise est protégé.
Mais on peut y voir un désavantage: si le serveur veut changer le taux
d'une devise, il ne le peut pas.
L'objet devise géré par le client est une copie de celui créé par le serveur.
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 37
L'atelier 6 : cas 1 (1/2)
Méthodes
distantes
Client1 Serveur
ServeurPP
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 38
L'atelier 6 : cas 2
Dans ce cas, le serveur encapsule les 2 devises afin de pouvoir changer
leur taux à tout moment.
Le programme ServeurPP.java permet d'intervenir sur le serveur afin de
changer un des taux des devises.
Une fois le client lancé on s'aperçoit que même si on change le taux côté
serveur, il n'est pas impacté. Il conserve le taux initial car l'objet Devise
appartient à l'espace mémoire du client.
Le client peut changer le taux si l'attribut est accessible (public ou
setteur).
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 39
L'atelier 6 : cas 3
Ce cas permet de montrer comment on peut pallier au désavantage
énoncé précédemment. Le client ne récupère plus des objets Devise
mais il réalise autant de connexion que de serveur.
Le programme ServeurPP crée autant de Serveur qu'il existe de devise à
gérer
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 40
L'atelier 6 : cas 4
Si on analyse la cas précédent, on s'aperçoit que la notion de "Serveur"
correspond à une Devise qui ferait des exportations de services RMI.
Les classes Serveur.java et ServeurInt.java disparaissent et sont
remplacées par les classes Devise.java et DeviseInt.java.
On appelle une instance de la classe Devise un Objet Distribué.
convertir1()
Devise1 setTaux
convertir2()
changer le taux
Client1 ServeurPP
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 41
L'atelier 6 : cas 5
Un désavantage du cas précédent est que le client doit savoir à priori
quelles devises le serveur gère.
Dans le cas 5, le client se connecte au serveur de devise qui gère les
devises et qui permet de signaler au client quelles devises il gère :
la classe Serveur : gère les devises
la classe Devise : gère 1 devise
convertir1()
Devise1 setTaux
convertir2()
changer le taux
convertir1()
Devise2 setTaux
convertir2()
getNomDevises() Serveur
Client1 ServeurPP
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 42
L'atelier 6 : Cas 6
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 43
Les autres ateliers sur RMI
Cours "Systèmes et réseaux répartis" NFP 214 par Jacques LAFORGUE (jacques.laforgue@neuf.fr) version du 04/02/2010 slide numéro 44