1 RPC/RMI ENSI-II2-RSR/SLE
Programmation d’Applications Réparties avec RPC et Java RMI
F. Najjar
RPC/RMI
Programmation réseau sous Unix
L’utilisateur ne peut accéder directement aux protocole situés dans le noyau
d’Unix
Il peut utiliser les protocole TCP et UDP par le biais des sockets
Les sockets peuvent être vues comme des portes vers le réseau
Les sockets offrent, pour la programmation, une interface similaire à celle
du système de fichiers
Le programmeur peut accéder directement aux points d’entrées de la couche 4
que forment les sockets sans avoir à traverser les couches 5 et 6
Ce qui est contraire aux règles imposées par le modèle de référence OSI de
l’ISO
2
3 RPC/RMI
RPC?
RPC-- Remote procedure call?
Appel de procédures/fonctions à distance Abstraction:
Vis-à-vis du protocole de communication Distribution masquée (transparence)
4 RPC/RMI
Composants de RPC?
IDL-- Interface Definition Language: langage de description des
données et des fonctions proche du C;
une méthode de représentation portable des données;
un protocole d’appel :
transmission des paramètres de l’appel du client vers le serveur;
transmission du résultat du serveur vers le client;
un protocole de publication et de recherche d’un service.
5 RPC/RMI
Types RPC
RPC par host-serveur: le client doit spécifier le host-serveur.
Deux grandes normes (traditionnelles):
SUN ONC/RPC --Open Network Computing/Remote Procedure Call
OSF DCE -- Open Software Foundation - Distributed Computing
Environnment.
Mais aussi RPC par objet-serveur : le client ne désigne pas le host-serveur
OMG CORBA -- Object Management Group -Common Object Request Broker
Architecture
SUN Java RMI -- Remote Method Invocation
Microsoft – DCOM -- Distributed Component Object Model
6 RPC/RMI
Types RPC (suite)
Et RPC intégrées dans les systèmes de composants:
SUN J2EE EJB -- Java 2 (Platform) Enterprise Edition - Enterprise Java
OMG CCM -- Object Management Group - Corba Component Model
WS-SOAP -- Web Services - Simple Object Access Protocol
7 RPC/RMI
ONC RPC (SUN)
rfc 1831 Solution classique, disponible sur Unix (incluse dans le système en général) et sous windows; « Open source », comparable aux DCE RPC en “gratuit” Il utilise le protocole XDR pour la description/échange de données (transport des arguments et du résultat) -- (rfc 1832) ; Technologie utilisée par NFS--Network File System. Outil de base rpcgen:
génère des convertisseurs ((un)marshalling); génère les souches (serveurs et clients); propose des modèles pour le client et le serveur engendre un Makefile; Utilise un lookup service pour la publication et la découverte d’un service (rfc 1833);
Service lookup tourne sur chaque hôte contenant des serveurs rpc.
Les RPC ONC peuvent être implantées sur n’importe quelle couche transport (TCP/UDP)
8 RPC/RMI
Représentation de Données (en mémoire)
Client et serveur sur machines différentes
Il faut transmettre données et résultats
Différences de représentations en mémoire
Codage Little-endian (x86, alpha) vs. Big-endian (ppc, sparc, reseau) :
(depend du processeur)
Représentation des flottants (fixe par IEEE 754)
Alignement des données dans structure (dépend du compilateur)
Tailles (32 ou 64 bits ; 4 ou 8 octets pour un registre)
9 RPC/RMI
XDR –eXchange Data Representation
Représentation portable des données (réseau):
codage big endian avec des mots de 4 octets (complétion par des zéros)
permet de définir des types de données associés à une
représentation binaire standard
Représentation commune sur le réseau (format pivot)
orienté C (syntaxe proche du C):
types fondamentaux classiques (int, double, etc.)
énumération
struct et union
tableaux
rpcgen engendre des fonctions de traduction à partir d’un fichier XDR
(et des bibliothèques de conversion de bas niveau) en XDR
10 RPC/RMI
XDR –Types (1/2)
Type
Identificateur
taille
Entier relatif
int
4 octets (IEEE)
Entier positif
unsigned int
4 octets (IEEE)
Enumération
enum {id = constante, …}
4 octets (IEEE)
Booléen
Entier long
bool
hyper
Entier positif
unsigend hyper
Enum {False=0, True=1}
8 octets
8 octets
Type
Identificateur
taille
Réels simples
Float
Réels doubles
double
4 octets (IEEE)
4 octets (IEEE)
Réels long
quadruple
4 octets (IEEE)
Rien
void
0 octet
11 RPC/RMI
XDR –Types (2/2)
Données à taille fixe ou variable :
[n] correspond à une taille fixe égale à n
<> correspond à une taille variable
<m> correspond à une taille variable inférieure à m
exemple, int<15> : liste d’entiers de longueur au plus 15.
Cas particuliers :
Identificateur
Contenu
opaque
string
Liste d’octets
Chaîne de caractères
12 RPC/RMI
Principe de base de SUN RPC
Un service réseau est fourni par plusieurs programmes
Un programme fournis plusieurs fonctions (ou procédures)
Un client appelle une procédure d’un programme
13 RPC/RMI
Le protocole RPC --Identification
Une procédure est identifiée par trois entiers (positifs) :
Hostname (IP Address)
Le numéro de programme unique (32 bit integer)
Sun divise les IDs en :
0x00000000 - 0x1fffffff Serveurs officiels Sun 0x20000000 - 0x3fffffff Publique (Admin. système) 0x40000000 - 0x5fffffff Serveurs Transitoires 0x60000000 - 0xffffffff Réservée par Sun
Le numéro de procédure (32 bit integer)
Commence toujours à partir de 1 et puis incrémenter séquentiellement.
Le numéro de version du programme (pour tests et migration)
Commence typiquement à partir de 1 et puis incrémenter
14 RPC/RMI
Le Langage de Description RPCL (1/2)
IDL de RPC
Les fichiers spécification d’extension ‘’.x ’’ ont la structure suivante:
[Définition des constantes]
[Définition des types]
program NOM_PROGRAMME {
[version NOM_VERSION {
[type_resultat nom_procedure
(type_du_parametre) = numero_procedure;]
} = numero_version]
} = numero_programme;
15 RPC/RMI
Le Langage de Description RPCL (2/2)
Les constantes :
const identificateur = valeur;
Les structures :
struct nom_du_type {
type attribut ;
}
Nouveau type:
typedef type nom_du_type ;
Cas particulier des tableaux et chaînes de caractères :
typedef int vecteur <1000>
typedef string chaine <255>
Liste des services RPC enregistrés sur une machine 16 RPC/RMI
Liste des services enregistrés:
rpcinfo –p [machine]
Appel de la procédure 0 d’un programme en utilisant le protocole udp
rpcinfo -u machine num_prg [num_version]
rpcinfo -t machine num_prg [num_version]
Exemple: rpcinfo -p
portmapper
portmapper
program no_version 100000 2
protocole tcp
no_ port 111
100000 2
udp
111
100021 1 udp 100021 3 udp 100021 1 tcp 100007 2 udp 100007 1 udp
32768 nlockmgr 32768 nlockmgr 32768 nlockmgr 705 ypbind 705 ypbind
100007 2 tcp
708 ypbind
100007 1 tcp 100003 2 udp
708 ypbind 2049 nfs
17 RPC/RMI
RPCGEN
18 RPC/RMI
Exemple: Helloworld.x
Le fichier de description helloworld.x
typedef string chaine<255>;
program HELLO_WORLD_PROG {
version HELLO_WORLD_VERSION_1 {
void hello_world_null(void)=0; /* tester le réseau et le serveur; sorte de ping*/
chaine hello_world(chaine)=1;
}=1;
} = 0x22222220;
rpcgen helloworld.x
rpcgen -a helloworld.x
helloworld.h (fichier entête)
Makefile
helloworld_xdr.c (filtre xdr)
Publicité
helloworld_server.c //prog. Squelette
helloworld_svc.c (souche serveur)
hello_client.c //prog squelette
helloworld_clnt.c (souche client)
19 RPC/RMI
helloworld_server.c
/* This is sample code generated by rpcgen . These are only templates and you can use them as a guideline for developing your own functions.*/ #include "helloworld.h" void * hello_world_null_1_svc(void *argp, struct svc_req *rqstp) {
static char * result; printf ("Ping\n");fflush (stdout); return (void *) &result;
} chaine * hello_world_1_svc(chaine *argp, struct svc_req *rqstp) {
static chaine result; static char tab[255]; /* insert server code here */ result=tab; strcpy (result, "Hello "); strcat (result, *argp); printf ("Result: %s\n", *argp); printf ("Result: %s\n", result); return &result;
}
20 RPC/RMI
helloworld_client.c
#include "helloworld.h“
void hello_world_prog_1(char *host) { CLIENT *clnt; void *result_1; char *hello_world_null_1_arg; chaine *result_2; chaine hello_world_1_arg; /* On établit la connexion en spécifiant le host, le #prog, le #version et le transport utilisé */ clnt = clnt_create (host, HELLO_WORLD_PROG, HELLO_WORLD_VERSION_1, "udp");
if (clnt == NULL) { clnt_pcreateerror (host); result_1 = hello_world_null_1((void*)&hello_world_null_1_arg, clnt); if (result_1 == (void *) NULL) {
exit (1); }
clnt_perror (clnt, "call failed"); }
result_2 = hello_world_1(&host, clnt); if (result_2 == (chaine *) NULL) clnt_perror (clnt, "call failed"); printf ("%s\n",*result_2); clnt_destroy (clnt); /* on coupe la connexion*/
int main (int argc, char *argv[]) { if (argc < 2) { printf ("usage: %s server_host\n", argv[0]); exit (1); } hello_workd_prog_1(argv[1]);}
21 RPC/RMI
Création du serveur & client
rpcgen helloworld.x
gcc –o server helloworld_server.c helloworld_xdr.c helloworld_svc.c –lrpcsvc -lnsl
./serveur &
rpcinfo –p
rpcinfo –u num HELLO_WORLD_PROG 1
gcc –o client helloworld_client.c helloworld_xdr.c helloworld_clnt.c –lnsl
./client
22 RPC/RMI
Publication et Résolution
Un problème standard des systèmes distribués :
pour le serveur, se faire connaître (publication)
pour le client, trouver le serveur (découverte et résolution)
Plusieurs niveaux :
1.partie facile : nom de la machine du serveur + DNS connexion possible
(TCP/UDP)
2.quelle couche transport ?
3.pour TCP/UDP, quel numéro de port ?
Solution proposée par les RPC ONC, un programme de binding (RFC 1823) :
le portmapper (version 2) : spécifique à TCP/UDP
le portmapper est lui-même un serveur rpc.
rpcbind (versions 3 et 4) : indépendant du transport
23 RPC/RMI
Binding RPC
Principes communs aux différentes versions:
le binder est un programme RPC de numéro 100000
il écoute toujours sur les ports 111 UDP et TCP
Le portmapper offre différentes fonctions :
publication d’un programme (décrit par son #programme et son #version)
suppression d’un programme
découverte (résolution) d’un programme, c’est-à-dire obtention du port associé à un
programme
obtention de la liste des programmes enregistrés
Appel direct d’une fonction distante
Le portmapper est limité à TCP et UDP.
24 RPC/RMI
RPCbind
Remplace le portmapper.
Principaux avantages :
indépendant du transport
permet un enregistrement et une résolution incluant les informations de
transport:
offre quelques nouvelles fonctions :
horloge
statistiques d’utilisation
un programme peut enregistrer plusieurs instances correspondant à
différents transport (avec le portmapper, le transport est automatique
celui utilisé pour contacter le portmapper lui-même)
25 RPC/RMI
Conclusion --Bilan des RPC
XDR?? CDR dans CORBA
26 RPC/RMI
Java RMI –
Programmation Répartie en Java
27 RPC/RMI
Programmation orientée objet --Rappel
Penser orienté objet (OO)?
Objet: collection de données et opérations
Classe: description d’un ensemble d’objets
‘’similaires’’, ayant des
propriétés communes.
Sous-classe: sous-ensemble d’une classe + propriétés complémentaires.
Instance: terme technique d’un objet d’une classe
Méthode: corps d’une procédure
Message: appel de procédure; demande d’une méthode
28 RPC/RMI
Intérêts des objets dans la programmation répartie
Encapsulation: Interface bien définie ; Etat interne masqué.
Classes et instances: Génération d'exemplaires selon un modèle.
Héritage: Spécialisation récupération et réutilisation de code.
Polymorphisme: Objets d'interface compatible interchangeables
Facilite l‘ évolution et l'adaptation des applications
29 RPC/RMI
Client/serveur orienté objet
But: coupler la notion d'objet avec les concepts client/serveur
Objectifs:
meilleure modularité des applications;
entités logiciels plus réutilisables;
applications mieux packagées, portables et maintenables plus
facilement
Résultats:
unité de distribution (et de désignation) = objet
objet = un ensemble de traitement fournis par ses méthodes
interaction client/serveur = invocation de méthode
Nombreux aspects techniques à intégrer pour y arriver
30 RPC/RMI
Client/serveur orienté objet --Challenges
1)Nommage –identification unique dans un environnement réparti
on parle de référence, qui sert à «retrouver» l’objet pour pouvoir
invoquer ses méthodes.
2) Sécurité d’accès –gestion du partage dans un env. réparti
3) Durée de vie (temporaire –durée de vie du créateur, persistante –durée de
vie du système)
4) Objets concurrents –2 types d’objets concurrents:
Passif: L’activité est manipulée de façon explicite,
orthogonal à l’objet,
et se «plaque» sur les méthodes. Exp. Les threads Java
Actif: une (+ieurs) activité(s) dédiée (s) à
l’objet exécutent les méthodes
31 RPC/RMI
Client/serveur orienté objet –Challenges (suite)
1)Synchronisation –concurrence d’exécution des méthodes
3 types de synchronisations
pour 1 méthode d'un objet (sémaphores, moniteurs, …)
synchronisation intra-objet (état d’exécution de l’objet)
synchronisation comportementale (état des données de l’objet)
pour plusieurs méthodes situées sur des objets différents
synchronisation inter-objets
2) Migration –déplacement d’objets (d’un site à un autre, …)
Pb. Impact de la migration sur la référence?
3) Réplication
4) Ramasse-miettes --Détruire les objets qui ne sont référencés par aucun
autre
2 techniques: compactage de références et traçage
32 RPC/RMI
Des RPCs aux RMIs
RMI –Remote method invocation (Invocations de méthodes à distance)
RPC “orientés objet” ;
Interaction d'objets situés dans des espaces d'adressage différents sur
des machines distinctes.
Simple à mettre en œuvre:
un objet distribué se manipule comme tout autre objet Java
33 RPC/RMI
Des RPCs aux RMIs --Différences
Interface Java: l’IDL est java lui-même
Passage d’arguments:
RPC: par valeur (copie)
RMI: par référence d’objet
elle contient tout ce qui est nécessaire pour atteindre
l’objet distant;
Localisation, protocole d’accès.
Localisation du serveur de noms (rmiregistry):
Localisation de chaque objet-serveur sur le host-serveur.
34 RPC/RMI
Références d’objet
Notion clé pour les objets répartis
Référence = moyen d’accès à un objet distant Pointeur universel En général une référence est “opaque” (son contenu ne peut pas être directement exploité) ; elle n’est utilisable que via un mécanisme d’appel à distance
Contenu d’une référence
Toutes les informations nécessaires pour atteindre physiquement l’objet Site de résidence Numéro de port sur le site Localisation interne au serveur …
Exemples (cf détails plus loin)
En Java RMI : la référence est simplement le talon client (stub) En CORBA : format de référence spécifié (IOR : Interoperable Object Reference) En DCOM : format “propriétaire”
35 RPC/RMI
Des RPCs aux RMIs—Différences (suite)
Autres caractéristiques des RMIs
ramasse-miette réparti (Distributed Garbage Collector)
intégration des exceptions
chargement dynamique de “byte code” (codebase)
aspect sécurité, applets, persistance, proxy, serveur http
36 RPC/RMI
Java RMI –mode de communication
Appel synchrone de la méthode distante
client bloqué tout le temps de l'appel distant
1 thread par client côté serveur
Appel asynchrone
utilisation explicite d'un thread côté client !
Appels concurrents côté serveur
exclusion mutuelle avec le mot clef “synchronized”
37 RPC/RMI
Java RMI --Principe
Même schéma que RPC
Le programmeur fournit:
Description(s) d'interface (en Java)
Les objets réalisant les interfaces
Le programme du serveur, instanciant ces objets
Le programme du client, invoquant ces objets
L'environnement Java fournit
Un générateur de talons nommé rmic (dans 1.4, inutile dans 1.5)
Un service de noms (rmiregistry)
Un middleware pour l'invocation à distance (ens. de classes).
La faculté d‘exécuter du code généré ailleurs
38 RPC/RMI
Java RMI –Architecture logique
Client
Serveur
Invocation de la méthode distante
Talon client
Naming
TCP/IP
Objet distant
Talon serveur
Naming
TCP/IP
39 ENSI Systèmes et applications répartis
La couche des références distantes --Naming
Remote reference Layer
Permet d’obtenir une référence d’objet distribué à partir de la référence locale au stub.
Plusieurs protocoles d’invocation possibles :
Invocation point à point (Unicast) Invocation vers des groupes de réplication (Multicast)
Publicité
Stratégie de reconnexion (si un objet devient inaccessible)
Deux composantes coopérantes :
la composante côté client (client-side) la composante côté serveur (server-side)
Transmission de données entre couches transport par une connexion orientée flot
40 ENSI Systèmes et applications répartis
Les amorces (stub/skeleton)
Elles assurent le rôle d’adaptateurs pour le transport des appels
distants.
Elles réalisent les appels sur la couche réseau.
Elles réalisent l’assemblage et le désassemblage des paramètres
(marshalling, unmarshalling).
Une référence d’objets distribués correspond à une référence
d’amorce.
41 ENSI Systèmes et applications répartis
La souche serveur (skeleton)
La souche serveur :
Reçoit l’appel par une méthode unique (aiguilleur)
Désassemble le flot d’entrée des arguments
Prépare l’appel vers l’implémentation réelle de l’objet distant
Distribue l’appel vers la bonne méthode cible
Assemble les valeurs de retour ou les exceptions dans le flot de sortie
42 ENSI Systèmes et applications répartis
La souche client (stub)
La souche client —représentant local de l’objet distribué
Initie l’appel vers un objet distant (via la couche des
références distantes )
Sérialise les arguments sous forme d’un unique flot de sortie
Informe la couche des références distantes que l’appel peut être invoqué
Désérialise le flot d’entrée contenant la valeur de retour ou une exception
Informe la couche des références distantes que l’appel est achevé
43 ENSI Systèmes et applications répartis
La couche transport
Elle réalise les connexions réseaux basées sur les flots entre les JVMs.
La couche transport de Java-RMI effectue :
Mise en place, gestion, surveillance de la connexion
Ecoute des appels arrivants
Maintien d’une table d’objets distants pour l’espace d’adressage
Localisation du dispatcher pour la cible d’un appel distant et transmission
de la connexion
Elle emploie un protocole de communication propriétaire (JRMP : Java Remote
Method Protocol) basé sur TCP/IP.
Principe schématique des RMIs
objet client
objet serveur
Talon client
Talon serveur
Système de communication
état
Methode_1 . . Methode_n
référence
appel
44
Java RMI Mode opératoire côté serveur
rmiregistry
Naming
Stub
Serveur
Skeleton
JVM Client
JVM Serveur
Client
45
Java RMI Mode opératoire côté serveur
0- Création de l’objet-serveur. 1 - L'objet serveur s'enregistre auprès du Naming de sa JVM (méthode rebind) 2 - L’objet skeleton est créé, celui-ci 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é auprès du serveur de noms (rmiregistry). Le serveur de noms est prêt à fournir des références sur l’objet-serveur
46
Java RMI --Mode opératoire côté client
rmiregistry
Naming
Naming
Client
Stub
Skeleton
JVM Client
47
Serveur
JVM Serveur
Java RMI --Mode opératoire côté client
4 - L'objet client fait appel au Naming pour localiser l'objet
serveur sur le host-serveur (méthode lookup)
5 - Le Naming récupère les "références" vers l'objet serveur,
auprès de la rmiregistry
6 – Le naming installe l’objet Stub sur le poste client et
7 - retourne sa référence au client.
8 - Le client effectue l'appel au serveur par appel à l’objet local
Stub
48
Java RMI -- Manuel d'utilisation (1/3)
1)Codage
description de l’interface du service
Ici pas d’IDL séparé : Java sert d’IDL
écriture du code du serveur qui implante l’interface écriture du client qui appelle le serveur
2)Compilation
compilation des sources serveur (javac) création des Stub et Skeleton par le générateur rmic (automatique à partir de JDK 5.0)
3)Activation
lancement du serveur de noms (rmiregistry) une
référence distante
L'accès à java.rmi.registry.Registry)
chez
le
client
(par
lancement du serveur lancement du client
49
Java RMI -- Manuel d'utilisation (2/3)
50
Java RMI --Manuel d'utilisation (3/3)
Définition de l'interface de l'objet réparti
L’interface de l’objet distant doit : "extends java.rmi.Remote" Les méthodes (+ exceptions): "throws java.rmi.RemoteException" Paramètres sérialisables : "implements Serializable "
Ecrire une implémentation de l'objet serveur
classe : étend une des sous-classes de java.rmi.server.RemoteServer comme java.rmi.server.UnicastRemoteObject Pas de spécialisation et le constructeur doit exécuter l'instruction suivante : UnicastRemoteObject.exportObject(this);
5 Packages
java.rmi : pour accéder à des objets distants java.rmi.server: pour créer des objets distants java.rmi.registry: lié à la localisation et au nommage d’ objets distants java.rmi.dgc: ramasse-miettes pour les objets distants java.rmi.activation support pour l’activation d’objets distants.
51
Java RMI –Les exceptions
Toutes
les méthodes de
l’interface, considérée, peuvent
déclencher une exception du type 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.
52
Hiérarchie de classes Java
53
54 ENSI Systèmes et applications répartis
Exportation de l'objet
Pour exporter un objet :
Utilisation de la classe UnicastRemoteObject
L'objet reste alors actif et accessible en permanence
Si la JVM dans laquelle il s'exécute est arrêtée, l'objet disparaît et sa
référence également.
Variante possible : Activatable
Serveurs démarrables par le système (que quand il est sollicité)
Objet/Service persistant (non liés à la durée de vie d’un processus)
Les constructeurs proposent de définir un port sur lequel sera
exporté le service. Sinon un port quelconque sera choisi.
Plus complexe à utiliser
55 ENSI Systèmes et applications répartis
La classe UnicastRemoteObject (1/3)
Serveurs démarrés explicitement
Utilise des communications TCP
Pour des comm. P2P entre processus actifs
Unicast : l'objet de la classe implémentant l'interface n'existe qu'un en
seul exemplaire sur une seule machine
L'objet meurt avec la fin de l'exécution du serveur qui le lance
56 ENSI Systèmes et applications répartis
La classe UnicastRemoteObject (2/3)
La principale fonction de cette classe se manifeste lors de la création
d’une instance de l’objet distant étendant cette classe.
Le constructeur crée une instance de stub pour l’objet et retourne
ce stub comme résultat de la création
Le contenu d’un stub
Un stub contient essentiellement une variable ref de type
RemoteRef qui contient la localisation de l’objet (adresse IP, port)
Un appel de méthode se fait par appel de ref.invoke(…) qui
utilise les sockets pour la communication
57 ENSI Systèmes et applications répartis
La classe UnicastRemoteObject (3/3)
La classe abstraite RemoteObject redéfinit plusieurs méthodes de
Object et en ajoute pour les objets distants
hashCode, equals, toString
getRef, toStub, writeObject, readObject
La classe abstraite RemoteServer définit des méthodes communes à
tous les serveurs
unexportObject, getClientHost, …
La classe UnicastRemoteObject implémente les objets distants non
répliqués (mono-serveur)
exportObject, …
58 ENSI Systèmes et applications répartis
La classe Activatable
JDK1.2 introduit
un nouveau package java.rmi.activation
un objet activable doit dériver de la classe Activatable
un démon RMI rmid
qui active les objets à la demande ou au reboot de la machine
Info : jdk1.2.2\docs\guide\rmi\activation.html
La classe doit étendre Java.rmi.activation.Activatable et implémenter
l’interface distante
La classe doit déclarer un constructeur avec 2 arguments
java.rmi.activation.ActivationID, java.rmi.MarshalledObject
59 ENSI Systèmes et applications répartis
Le service de nommage
Une URL est formée pour l'enregistrement puis l'accès sous la forme :
rmi://<host_name>[:port]/[Remote_service_name]
Le host_name est, par défaut, le localhost
Le port de liaison est optionnel (par défaut, le port TCP 1099)
défini (ou à définir) dans /etc/services : rmi 1099/tcp
La classe Naming encaspule le dialogue avec plusieurs objets serveur de liaison
Peut utiliser un ou plusieurs registry par application distribuée
On doit enregistrer un objet sur un registry local
5 opérations statiques pour enregistrer des objets et récupérer leurs références
60 ENSI Systèmes et applications répartis
Le service de nommage
Les objets serveur de liaison réalise la correspondance nom avec stub:
Publicité
Interface d’un objet serveur de liaison
Implémentation par défaut de l’objet serveur de liaison
La classe LocateRegistry
localise ou active un objet serveur de liaison En général invisible au client (appelé en interne par Naming)
Méthodes Statiques
Registry createRegistry(int port)
–crée un objet serveur de liaison sur le port spécifié
Registry getRegistry(int port)
–récupère l’objet serveur de liaison qui a été crée
Registry getRegistry(server name, port number)
–essaie de trouver un démon rmiregistry sur la machine server name et sur le port port number
61 ENSI Systèmes et applications répartis
Le service de nommage
62 ENSI Systèmes et applications répartis
La notion d’interface
L’interface constitue le contrat (abstrait) liant objets serveurs et objets
clients Elle est partagée par le client et le serveur.
elle est destinée à être implémentée par l’OD et constitue la base
d’appel pour les objets clients
elle définie les signatures (noms, types de retour, paramètres) d’un
ensemble de méthodes et seules ces méthodes seront accessibles par
un objet client.
Pour RMI, c’est une interface Java traditionnelle … mais dérivant de la
classe java.rmi.Remote
Java RMI : écriture de l’interface
Mêmes principes de base que pour l’interface d’un objet local
Principales différences
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
tout objet distant passé en paramètre doit être déclaré comme une interface (passage de la référence de l’objet)
tout objet local passé en paramètre doit être sérialisable
63
Exemple de client/serveur en Java RMI
Cas simple :
Le client connaît le nom du serveur
La rmiregistry est lancée sur le serveur
Le client passe des arguments « de base »
64
Java RMI Exemple : Interface Hello.java
// Hello.java
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
String sayHello() throws RemoteException;
Description de l’interface
}
65
Java RMI : écriture du serveur
Serveur = la classe qui implémente l’interface
spécifier les interfaces distantes qui doivent être implémentées
locaux passés par copie (ils doivent
objets l’interface java.io.serialisable) objets distants passés par référence (actuellement référence à un stub)
implémenter
c’est un objet java standard
définir le constructeur de l’objet; fournir la mise en œuvre des méthodes pouvant être appelées à distance; ainsi que celle des méthodes n’apparaissant dans aucune interface implémentée.
créer au moins une instance du serveur
enregistrer au moins une instance dans le serveur de nom
(rmiregistry)
66
67 ENSI Systèmes et applications répartis
Java RMI : écriture du serveur
L’objet distant servi peut être d’une sous classe de la classe implémentant l’interface
Le serveur peut créer et enregistrer plusieurs objets appartenant à une ou plusieurs classes
L’enregistrement de l’objet distant se fait dans rmiregistry (un ou +ieurs).
Il faut prévoir une procédure d’arrêt (shutdown) du serveur
Arrêt des objets UnicastRemoteObject
public static void Naming.unbind(Stringname) public
static
UnicastRemoteObject.unexportObject(Remote, boolean force)
boolean
Java RMI Exemple : Implémentation de l’objet distant
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject;
public class HelloObj extends UnicastRemoteObject implements Hello {
fichier HelloObj.java
private String msg;
// Constructeur
public HelloObj(String msg) throws RemoteException {
this.msg = msg;
}
// Implémentation de la méthode distante.
public String sayHello() throws RemoteException {
return "Hello world: " + msg;
Réalisation du serveur
}
}
68
Java RMI Exemple : Implémentation de l’objet distant
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject;
public class HelloObj implements Hello { private String msg;
fichier HelloObj.java
Réalisation du serveur (autre approche)
// Constructeur
public HelloObj(String msg) throws RemoteException {
this.msg = msg; UnicastRemoteObject.exportObject(this);
}
// Implémentation de la méthode distante.
public String sayHello() throws RemoteException {
return "Hello world: " + msg;
}
}
69
Java RMI Exemple : Serveur
import java.rmi.*;
public class HelloServeur {
fichier HelloServeur.java
Réalisation du Serveur d’objets
public static void main(String args[]) {
try {
// Crée une instance de l’objet serveur –démarrage du serveur HelloObj obj = new HelloObj("HelloServeur");
// Enregistre l'objet créé auprès du serveur de noms. Naming.rebind("rmi://localhost:1099/HelloServeur", obj); System.out.println("HelloServer" + " bound in registry");
} catch (Exception exc) {… }
}
}
ATTENTION: dans cet exemple le serveur de nom doit être activé avant la création du serveur.
70
71
Java RMI Activation du serveur de nom par le serveur
HelloServeur.java public static void main(String args[]) { int port; String URL;
fichier
try { // transformation d ’une chaîne de caractères en entier Integer I = new Integer(args[0]); port = I.intValue(); } catch (Exception ex) { System.out.println(" Please enter: Server <port>"); return; }
Réalisation du serveur (autre approche)
try { // Création du serveur de nom - rmiregistry Registry registry = LocateRegistry.createRegistry(port);
// Création d’une instance de l’objet serveur HelloObj obj = new HelloObj("Coucou, je suis le serveur de port : "+port);
// Calcul de l’URL du serveur URL = « rmi://"+InetAddress.getLocalHost().getHostName()+":"+port+"/" +
Hello.class.getName();
registry.rebind(URL, obj); } catch (Exception exc) { ...
72
Java RMI Exemple : Client
import java.rmi.Naming;
public class HelloClient { public static void main(String args[]) { try {
fichier HelloClient.java
// Récupération d'un stub sur l'objet serveur. Hello obj = (Hello) Naming.lookup("rmi://LocalHost/HelloServeur"); // Appel d'une méthode sur l'objet distant. String msg = obj.sayHello(); // Impression du message. System.out.println(msg); } catch (Exception exc) { … } }}
Réalisation du client
On récupère en fait une référence sur une instance de HelloObj_Stub
Le talon local côté client qui sert de proxy pour l'accès à l'instance de HelloObj côté serveur
Java RMI Exemple : Client (Recherche du rmiregistry)
fichier HelloClient.java
import java.rmi.Naming;
public class HelloClient { public static void main(String args[]) { try { // Récupération d'un stub sur l'objet serveur.
if (args.length > 0) obj = (Hello) LocateRegistry
.getRegistry(args[0]).lookup("rmi://LocalHost/HelloServeur");
else obj = (Hello)LocateRegistry.getRegistry()
.lookup(Hello.class.getName());
// Appel d'une méthode sur l'objet distant. String msg = obj.sayHello(); // Impression du message. System.out.println(msg); } catch (Exception e) {System.out.println("HelloClient err: " + e.getMessage());
Réalisation du client
e.printStackTrace(); }
}}
73
Java RMI Compilation
Compilation de l’interface, du serveur et du client
javac Hello.java HelloObj.java HelloServeur.java HelloClient.java
Génération des talons
Générés automatiquement à partir du JDK 5.0
rmic sur la classe d’implémentation (JDK 1.4 ou antérieur)
rmic HelloObj
skeleton dans HelloObj_Skel.class
stub dans HelloObj_Stub.class.
Les fichiers .java générés sont effacés sauf si l'option -
keepgenerated est spécifiée.
74
Java RMI Déploiement
1) Activation du serveur de nom
rmiregistry & (Unix) ou start rmiregistry (Windows)
2)Activation du serveur
java HelloServeur &
L'exécution d'un serveur RMI nécessite de fixer quelques propriétés:
L'hôte et le chemin d'accès des classes (de l'interface, éventuellement des
implémentations) du serveur.
Le fichier définissant la politique de sécurité
–-Djava.security.policy=<fichier_policy>
3)Activation du client
java HelloClient
75
Security Manager et Codebase (1/2)
Utilisation d'un Security Manager
On installe un gestionnaire de sécurité si le serveur est amené à charger
des classes (inutile si les classes ne sont pas chargées dynamiquement).
if (System.getSecurityManager() == null) {
System.setSecurityManager(new SecurityManager());
}
Politique de sécurité (fichier all.policy)
grant {
permission java.security.AllPermission; };
Prise en compte de la politique de sécurité
java -Djava.security.policy=all.policy …
76
Security Manager et Codebase (2/2)
Utilisation du codebase avec HTTP (extension du classpath)
-Djava.rmi.server.codebase=<repertoire>
Exemple :
java -Djava.rmi.server.codebase=http://LocalHost/… HelloServeur
path indiquant à quel endroit la machine virtuelle cliente va pouvoir
chercher le code du stub
-Djava.rmi.server.hostname=<hote>
Nécessaire si le client et le serveur ne sont pas sur la même station
77
78 ENSI Systèmes et applications répartis
Passage d'arguments (1/2)
Différence dans le passage d'arguments (objets locaux /objets
distants):
Tous les objets locaux sont passés par valeur.
Tous les objets distants sont passés par référence.
L’argument est un objet de base (int, double, …): passage par valeur
L’argument est un objet local
L’objet doit être sérialisé et envoyé au serveur
il doit donc implém