Application répartie sur un réseau
• Deux applications communiquent via un réseau
– L'application serveur
• Créé un port de communication
Applications réparties en Java •
•
Créé des services
Attend les demandes de service effectuées par les clients
• Réponds aux demandes en envoyant des valeurs
– L'application client
Paquetage java.net – Sockets • Se connecte au p
port de communication
Objets distants transparents – RMI • Effectue des demandes de service par l’envoie de valeurs sur le port de
communication
• Attend les réponses sur le même port
Yves Bekkers
Message de demande de service
client réseau serveur
Retourner le résultat
sockets/rmi - Y. Bekkers 1 sockets/rmi - Y. Bekkers 2
Paquetage java.net
Communication par message
• Classes pour l’implémentation d’applications réseau
• Soit un service correspondant à une procédure de la forme – Identification des machines
TypeResultat NomDuService(Type1, ... Typek) • java.net.InetAddress
• le client Classes pour représenter une adresse IP (protocole Internet)
– envoit un message de la forme : • java.net.URL
CodeService, p1, ... pk Classes pour représenter une URL sur Internet
– se met en attente du résultat,
résultat – Ports de communication
– après réception du résultat, décodage du résultat • java.net.Socket
• le serveur Extrémité d’une communication entre deux machines
– reçoit le code du service demandé, le décode (au moyen d’un Port coté client
switch par exemple), Supporte des flux de données bidirectionels
• java.net.ServerSocket
– reçoit les k paramètres en les décodant et en restituant leur types
respectifs, Extrémité d’une communication entre deux machines
– appelle la procédure de ce service Port coté serveur
Attend les demandes de services arrivant sur le port
– code le résultat et le retourne au client par message.
sockets/rmi - Y. Bekkers 3 sockets/rmi - Y. Bekkers 4
Sockets TCP Classe Socket
• Connection point à point • Constructeurs
public Socket(String hote, int port) throws
• Classe Socket UnknownHostException, IOException
– Connexion à une machine distante public Socket(InetAddress hote, int port)
throws IOException
– Envoi/Réception de données
• Envoi/Réception de données
– Fermeture d’une connexion public InputStream getInputStream() throws
• Classe SocketServer IOException
public OutputStream getOutputStream() throws
– Attachement à un port IOException
– Acceptation d’une demande de connexion à un port local • Fermeture
– Attente de demandes de connexion public synchronized void close() throws
IOException
sockets/rmi - Y. Bekkers 5 sockets/rmi - Y. Bekkers 6
1
Appels de méthodes à distance Schéma de l’application
• Une interface commune entre les clients et le serveur
public interface Personne {
public int getAge() throws Throwable; Serveur
public String getName() throws Throwable;
}
Client
• Deux implémentations de l’interface
– Coté
C té client
li t Personne_stub
• Connection au port de communcation
• Sérialisation (codage) des demandes
• Attente et décodage du résultat
– Coté serveur Personne_skel
• Mise en place d’un port de communcation
• Attente et décodage des demandes de service
• Codage et renvoie du résultat
sockets/rmi - Y. Bekkers 7 sockets/rmi - Y. Bekkers 8
Classe Personne_Stub
Simuler des appels de méthodes à
• Constructeur
distance public Personne_Stub() throws Throwable {
pSocket = new Socket("localhost",9000);
getAge() }
client Personne_Stub
• Méthode getAge()
Sérialisation ObjectOutputStream outStream = new
ObjectOutputStream(pSocket.getOutputStream());
getAge() outStream.writeObject("age");
Personne_skeleton PersonneObject
outStream.flush();
Invoquer une méthode ObjectInputStream inStream = new
ObjectInputStream(pSocket.getInputStream());
return inStream.readInt();
client réseau serveur • Méthode close()
public void close() throws Throwable {
Retourner le résultat pSocket.close();
}
sockets/rmi - Y. Bekkers 9 sockets/rmi - Y. Bekkers 10
Classe Personne_Client Serveur
• Méthode main()
Personne_Stub p = new Personne_Stub();
int age = p.getAge();
String nom = p.getName();
p.close();
System.out.println(nom+" est agé de "+age+"
ans");
sockets/rmi - Y. Bekkers 11 sockets/rmi - Y. Bekkers 12
2
Classe Personne_Skeleton Classe Personne_Skeleton (1)
• Constructeur • Méthode run()
public Personne_Skeleton(PersonneObject // Création d’un nouvel objet ServerSocket
p) { ServerSocket serverSocket = new ServerSocket(9000);
while (true) {
this.myPersonne = p; Socket socket = serverSocket.accept(); // attente
} while (socket != null) {
ObjectInputStream inStream = null;
• Méthode main() try {
inStream = new
public static void main(String[] args) { ObjectInputStream(socket.getInputStream());
} catch (EOFException e) {// connection fermée
Personne_Skeleton skel = new socket.close();
Personne_Skeleton( break; // fin de service pour cette connection
}
new PersonneObject("paul", 25)); ...
}
skel.start(); }
}
sockets/rmi - Y. Bekkers 13 sockets/rmi - Y. Bekkers 14
Traiter une demande de service (2)
• Méthode run() suite
String service = (String) inStream.readObject();
if (service.equals("age")) {
int age = myPersonne.getAge();
ObjectOutputStream outStream =
new ObjectOutputStream(socket.getOutputStream());
RMI
outStream.writeInt(age);
outStream.flush();
Remote Method Invocation
} else if (service.equals("name")) {
String name = myPersonne.getName();
ObjectOutputStream outStream =
new ObjectOutputStream(socket.getOutputStream());
outStream.writeObject(name);
outStream.flush();
}
sockets/rmi - Y. Bekkers 15 sockets/rmi - Y. Bekkers 16
RMI rendre transparents les
Mise en place de services distants
échanges
• Sans RMI : Le concepteur de l’application • Définition d’objets distants :
fait tout le travail de transmission – Objets résidents sur un site et utilisés sur un autre
– Tâche de programmation lourde, dangereuse • Deux technologies concurrentes
(nombreuses sources d’erreur)
– CORBA : applications réparties faisant intervenir
• Avec RMI : mise en œuvre automatique du divers langages (C++, Smalltalk, Eiffel, Java, ...)
protocole de communication – RMI : une norme purement Java (Remote Method
Invocation).
sockets/rmi - Y. Bekkers 17 sockets/rmi - Y. Bekkers 18
3
RMI – programmation distribuée Structure d’une application RMI
Remote Machine
• Le serveur lie son nom à bind
• Protocole client/serveur propre à java. RMI Server
un objet Registry
– Package pour faire dialoguer des objets java par Internet. Registry
• Repose sur l’utilisation de la librairie java.net
• The client recherche le
nom du serveur et établie skeleton
• Un concurrent de Corba, avec quelques différences : une connection.
• Simplicité de mise en oeuvre
oe re : • Le
L talon
t l (Stub)
(St b) sérialise
é i li return call lookup
– Pas de serveur spécial, le serveur est une classe java les paramètres au
– transparence totale (intégration dans l'API Java) squelette,
• RMI : échange d’instances d'objets facilité grâce à : • Le squelette invoque la stub
– L’utilisation du Classloader de Java méthode distante et
– La réflexivité native de Java sérialise le résultat en RMI Client
• Inconvénients : Java uniquement retour vers le talon.
Local Machine
sockets/rmi - Y. Bekkers 19 sockets/rmi - Y. Bekkers 20
RMI – programmation distribuée
• Le code n'est pas localisé sur une unique machine,
• Il est déployé sur plusieurs machines en réseau.
Un exemple en 5 étapes
Site client Site serveur
réseau Serveur : localhost
...
Port : 8090
calc.somme(12,34); Résultat : 46 Service : calc
...
calc.somme(12,34);
sockets/rmi - Y. Bekkers 21 sockets/rmi - Y. Bekkers 22
Un exemple – calculateur distant (1) Interface d'objet distant
• Un site serveur définit un objet Convertisseur doté d’une • Un convertisseur
méthode toEuro() qui reçoit en paramètre une valeur (un import java.rmi.Remote;
float) et rend un résultat sous forme d’un float. import java.rmi.RemoteException;
• Sur un site client on peut accéder à cet objet par un nom public interface Conversion extends Remote {
externe qui est une chaîne de caractères formée du nom du public float toEuro(float x)
serveur, d’un numéro de p port, et d’un identificateur
throws RemoteException;
d’objet, de la forme :
}
//localhost:8090/convertisseur
• Le client obtient la référence de l’objet distant puis l’utilise • A noter
directement en appelant la méthode toEuro(). – Extension de l'interface Remote (objet distant)
– Prévoir que les méthodes sont susceptibles de
lancer des exceptions RemoteException
sockets/rmi - Y. Bekkers 23 sockets/rmi - Y. Bekkers 24
4
(2) Implémentation coté serveur (3) Compilation des objets distants
public class ConvertisseurImpl Extension de
extends UnicastRemoteObject
UnicastRemoteObject • Java 1.4 Deux compilations sont nécessaires
implements Conversion {
Implémentation – Compilation des interfaces et des
de l'interface implémentations d'objets distants
protected ConvertisseurImpl()
throws RemoteException {
javac –classpath . *.java
super(); Définir un – Compilation des souches et des squelettes
} constructeur d'objets distants
public float toEuro(float x) rmic –classpath . MyClassDistant
throws RemoteException {
return x/6.55957f;
• Java 1.5 une seule compilation
} – les objets distants sont découverts à l’exécution
} par des « proxies »
sockets/rmi - Y. Bekkers 25 sockets/rmi - Y. Bekkers 26
(4) Initialisation du site serveur et
Les souches et les squelettes enregistrement d’un objet distant
• Deux classes supplémentaires pour chaque objet public class ServeurConvertisseur {
distants public static void main(String[] args) {
try {
– La souche (stub) coté client émet les paramètres et
LocateRegistry.createRegistry(8090);
récupère les résultats ConvertisseurImpl euroConv = new
– Le squelette (skeleton) coté serveur reçoit les ConvertisseurImpl();
paramètres retourne le résultat Naming.bind(
"//e103c04.ifsic.univ-rennes1.fr::8090/testConv",
client serveur euroConv);
} catch (Exception e) {
System.out.println("erreur rmi");
stub skeleton }
WEB }
}
sockets/rmi - Y. Bekkers 27 sockets/rmi - Y. Bekkers 28
Étapes de mise en place du serveur Arrêt du service
• lancement d’un processus d’enregistrement de
service sur le port 8090 du « localhost » • Détruire le lien
LocateRegistry.createRegistry(8090); Naming.unbind(
"//localhost.irisa.fr:8090/testConv");
• Création de l'objet distant
ServeurConvertisseur euroConv =
new ServeurConvertisseur();
• Identification de l'objet
Naming.bind(
"//localhost:8090/testConv",
euroConv);
sockets/rmi - Y. Bekkers 29 sockets/rmi - Y. Bekkers 30
5
(5) Connexion d’un client à un objet
distant connu par son nom externe Utilisation d'un objet distant
public class ClientEuroConv {
public static void main(String[] args) {
try { • Mise en correspondance avec l'objet distant
Conversion euroConv = (Conversion) Naming.lookup( Conversion euroConv = (Conversion) Naming.lookup(
"//localhost:8090/testConversion"); "//localhost:8090/testConversion");
float x = Float.parseFloat(args[0]);
p ( g [ ]);
System.out.println("en entrée = " + x); • Utilisation de l'objet distant
System.out.println("En sortie = " + float x = Float.parseFloat(args[0]);
euroConv.toEuro(x));
System.out.println("en entrée = " + x);
} catch (Exception e) {
System.out.println("Erreur rmi"); System.out.println("En sortie = " +
} euroConv.toEuro(x));
}
}
sockets/rmi - Y. Bekkers 31 sockets/rmi - Y. Bekkers 32
Mode de passage de paramètre et
Type des arguments et des résultats
de résultat
• Pratiquement tous les types d'arguments et • Objets Distants (Remote)
de résultats sont acceptés – Passage par référence (stub)
– Types primitifs • Seules les méthodes de l'interface Remote sont
disponibles
– Objets distants
• Les modifications sont faites sur l'objet original
• ceux qui implémentent java.rmi.Remote
– Types non-primitifs sérialisables • Objets locaux
• ceux qui implémentent java.io.Serializable – Passage par copy (à l'aide de la sérialisation)
• Les modifications sont faites sur la copie
sockets/rmi - Y. Bekkers 33 sockets/rmi - Y. Bekkers 34
Mise en place sur un serveur http Dissémination des références
classique • En règle générale, dans une application répartie,
• Côté serveur : seul un objet (ou quelques objets) est (sont)
– MyClassDistant_Skel.class
connu(s) par un nom externe, un objet “serveur
central” de l’application répartie.
– mettre les .class des interfaces locales et distantes
• Cet objet préexistant est le germe dd’activités
activités qui
• Côté client : ensuite créent d’autres objets distants et se les
– MyClassDistant_Stub.class
communiquent par paramètres ou résultats de
– (si le serveur transmet des objets locaux particuliers, il procédures, de façon tout à fait conventionnelle,
doit les fournir, comme ferait un client) comme si ces objets étaient situés sur le même
site.
sockets/rmi - Y. Bekkers 35 sockets/rmi - Y. Bekkers 36
6
Références Le tp
• Tutorial Sun
http://java.sun.com/docs/books/tutorial
/rmi/index.html
sockets/rmi - Y. Bekkers 37 sockets/rmi - Y. Bekkers 38
Deux interfaces
• ServeurSession Interfaces de saisie
public interface ServeurSession extends Remote {
public Repondeur ouvreSession() throws
RemoteException;
}
• Repondeur
public interface Repondeur extends Remote {
public void poseQuestion(String q) throws
RemoteException;
public String obtientReponse() throws
RemoteException;
public void fin() throws RemoteException;
}
sockets/rmi - Y. Bekkers 39 sockets/rmi - Y. Bekkers 40