RMI Remote Method Invocation: permet d'invoquer des méthodes d'objets distants. Méthode proche de RPC. Outils et classes qui rendent l'implantation d'appels de méthodes d'objets distants aussi simples que leur implantation dans en local. RMI 1 Modèle RMI RMI 2 1 1
Modèle RMI La souche (Stub client): implante la même interface que l'objet distant. transforme l'appel de méthode en une suite d'octets à envoyer sur le réseau (Marshaling) et de reconstruire le résultat reçu sous le même format (Unmarshaling). Le squelette (Skeleton ou souche serveur): reconstruit les paramètres, trouver l'objet appelé et appelle la méthode. retourner le résultat. RMI 3 Le protocole RMI Client Hello Où est Hello? Registre Il est ici! Envoyez le stub! HelloImp_stub.class Stub Le voici! dishello() HelloImp_skel.class Client «Hello!» HelloImp.class Serveur RMI 4 2 2
Développement d'applications RMI Écrire l'interface de l'objet distant. Écrire l'implantation de cette interface. Générer les Stub/Skeleton correspondant. Exporter l'objet implémentant l'interface, l'objet distant attend alors les requête via le Skeleton. Appeler une méthode de l'objet via le Stub. RMI 5 Définition de l'interface Un objet distant est une instance d'une classe qui implémente l interface et sous classe l'interface java.rmi.remote et déclare un ensemble de méthodes distantes. Chaque méthode distante doit jeter java.rmi.remoteexception import java.rmi.remote; import java.rmi.remoteexception; public interface Hello extends Remote { String sayhello() throws RemoteException; RMI 6 3 3
Le client Le programme client obtient la souche du registre sur le serveur. Cherche le stub de l objet distant par son nom dans les registre et invoque la méthode de l objet distant Le client récupère une référence sur l'implémentation distante via le nom qui lui a été attribué précédemment, puis appelle sur cette référence la méthode distante, comme si elle était locale. RMI 7 Le client import java.rmi.registry.locateregistry; import java.rmi.registry.registry; public class Client { public static void main(string[] args) { String host = (args.length < 1)? null : args[0]; try { Registry registry = LocateRegistry.getRegistry(host); Hello stub = (Hello) registry.lookup("hello"); String response = stub.sayhello(); System.out.println("response: " + response); catch (Exception e) { System.err.println("Client exception: " + e.tostring()); e.printstacktrace(); RMI 8 4 4
L appel de la part du client Le client appelle la méthode sayhello sur la souche de l'objet distant, ce qui provoque les actions suivantes: Le client ouvre une connexion sur le serveur en utilisant le host et le port à partir de la souche de l'objet distant et sérialise les données de l'appel. Le serveur accepte l'appel entrant, effectue l'appel à l'objet distant et sérialise le résultat (ici «Hello, world!») au client Le client reçoit, désérialise et retourne le résultat à l'appelant. RMI 9 Le serveur La classe qui possède une méthode main() qui crée une instance de l'implémentation de l'objet distant, exporte l'objet distant et lie cette instance à un nom dans un registre. Le serveur : Crée et exporte l objet distant Enregistre l'objet distant auprès d un registre RMI RMI 10 5 5
Le serveur import java.rmi.registry.registry; import java.rmi.registry.locateregistry; import java.rmi.remoteexception; import java.rmi.server.unicastremoteobject; public class Server implements Hello { public String sayhello() { return "Hello, world!"; public static void main(string args[]) { try { Server obj = new Server(); Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0); Registry registry = LocateRegistry.getRegistry(); registry.bind("hello", stub); System.err.println("Server ready"); catch (Exception e) { System.err.println("Server exception: " + e.tostring()); e.printstacktrace(); RMI 11 Le serveur Pour le serveur, on doit instancier la classe: java.rmi.server.unicastremoteserver. Sous classe de java.rmi.server.remoteobject. RemoteServer possède des méthodes telles que getclienthost() qui permet de connaître l'identité du client pendant un appel de méthode. RMI 12 6 6
Exporter un objet Pour être exporté, un objet doit implémenter la classe Remote. Lorsqu'un objet est exporté, un ensemble de threads est créé pour attendre les appels des méthodes. L'objet distant doit être exportée afin qu'il puisse recevoir des appels entrants: Server obj = new Server(); Hello stub = (Hello) UnicastRemoteObject.exportObject(obj, 0); RMI 13 Le service de nommage Pour enregistrer les objets il faut lancer le registre (service de nommage) : rmiregistry port & On enregistrer un objet au moyen de: bind(string name, Remote obj) rebind(string name,remote obj) RMI 14 7 7
Le service de nommage Le service de nommage permet de récupérer le Stub d'un objet distant à partir d'un nom. La classe Naming permet d'accéder au service de nommage d'une machine en utilisant un URL: rmi://machine:port/objet On récupère le Stub d'un objet distant à partir de son URL au moyen lookup(string name). Autres méthodes : unbind(string name) pour désenregistrer l'objet, list(string name) pour lister les objets enregistrés. RMI 15 Le service de registre Pour invoquer une méthode distante, l'appelant doit d'abord obtenir un stub pour l'objet distant. Java RMI fournit une API (de registre)pour que l'application lie un nom au stub d'un objet distant et pour les clients de trouver des objets distants par leur noms pour obtenir leurs stubs. Une fois un objet distant est enregistré sur le serveur, les appelants peuvent le rechercher par son nom, obtenir une référence d'objet distant, puis appeler des méthodes à distance sur l'objet. Registry registry = LocateRegistry.getRegistry(); registry.bind("hello", stub); RMI 16 8 8
Passage de paramètres et retours Les variables de type primitif sont passées par valeur. Les objets qui n'implémentent pas l'interface Remote sont passés par copie à condition qu'ils implémentent l'interface Serializable ou Externalizable. Les objets qui implémentent l'interface Remote sont remplacés par l'objet Stub correspondant lors du passage de paramètres. Le retour de valeur a la même sémantique. RMI 17 Sérialisation Java permet l'accès aux données externes via des streams: pour le stockage externe de données: streams de caractères streams d'octets pour permettre aux données de faire partie de l'objet stream d'objets Pour sauvegarder un objet (et ses données) sur un support externe (ex. disque) ou le transmettre (ex. par Intenet) on doit le sérialiser. RMI 18 9 9
Compilation et exécution du code Compiler les programmes: l interface en premier, le serveur puis le client: javac Hello.java, javac Server.java, javac Client.java Générer les fichiers stub et squelette pour le serveur: rmic HelloImpl Génére: Server.class, Server_Skel.class, Server_Stub.class Lancer le registre : rmiregistry 8888 & Lancer le serveur: java Server & Exécuter le client: java Client javac HelloImpl.java javac HelloServer.java javac HelloClient.java rmic HelloImpl RMI 19 10 10