3. LES SOCKETS: DÉFINITION
Le socket est un "canal" de communication bi-
directionnel entre deux processus se trouvant ou non sur
la même machine. Il est caractérisé par :
une adresse IP
un numéro de port
Pour créer un socket entre 2 processus, il faut que un
des deux processus soit en attente de demande de
création d'un socket de la part de l'autre.
On appelle le premier le serveur de socket, le deuxième le
client.
L'initiative de fermer le socket est normalement donnée au
serveur bien que le client peut fermer lui aussi le socket.
3
Imene Sghaier-Systèmes Répartis
4. LES SOCKETS: DÉFINITION
Le socket est créé à l'initiative du client.
Sur un même serveur, on peut créer plusieurs sockets de
port différents
Sur un même serveur, on peut créer plusieurs sockets
sur le même port à condition que chaque connexion se
fasse dans différents threads.
Une fois le socket créé, la communication se fait dans les
2 sens. On parle de "tube" de communication.
L'adresse IP du socket est l'adresse IP du serveur.
4
Imene Sghaier-Systèmes Répartis
5. LES SOCKETS: DÉFINITION
Les sockets permettront de gérer des flux entrant et sortant afin
d'assurer une communication entre le client et le serveur, soit de
manière fiable à l'aide du protocole TCP/IP, soit non fiable mais plus
rapide avec le protocole UDP.
Le mode connecté (communication téléphonique), utilisant le
protocole TCP. Une connexion durable est établie entre les deux
processus, de telle façon que l'adresse de destination n'est pas
nécessaire à chaque envoi de données.
Le mode non connecté (communication par courrier), utilisant le
protocole UDP, nécessite l'adresse de destination à chaque envoi, et
aucun accusé de réception n'est donné.
5
Imene Sghaier-Systèmes Répartis
6. EXEMPLES D’APPLICATIONS
Voici ce qu'on peut réaliser à l'aide des sockets :
des jeux en ligne ;
des systèmes distribués ;
Des canaux de communication
des espaces messengers comme MSN Messenger,
Yahoo Messenger, … ;
…
6
Imene Sghaier-Systèmes Répartis
7. LE PACKAGE JAVA.NET
Les classes de java.net.* permettent d‘établir des
flux d'entrées/sorties entre machines a l'aide de
sockets
Il existe deux protocoles utilisant les sockets en
Java :
TCP : Stream Socket
Communication en mode connecté
Les applications sont averties lors de la déconnexion
UDP : Datagram Socket
Communication en mode non connecté
Plus rapide mais moins able que TCP
7
Imene Sghaier-Systèmes Répartis
8. SOCKET EN JAVA
Les classes utilisés sont Socket et ServerSocket du
package java.net (API Java Réseau)
La classe ServerSocket permet côté serveur de se
mettre en attente d'une demande de création d'un
socket.
La classe Socket permet côté client de créer le socket
sur le serveur.
Des deux côté, la classe Socket permet de définir un
objet InputStream et OutputStream (flux d’entrée et
flux de sortie) permettant de lire ou d'écrire des
informations dans le tube de communication créé par le
socket. 8
Imene Sghaier-Systèmes Répartis
9. FONCTIONNEMENT D’UN SOCKET
Fonctionnement selon le protocole TCP
Fonctionnement selon le protocole UDP
Denir un paquet à envoyer ou à recevoir par la classe
DatagramPacket
Le paquet de données contient l'adresse de destination et la longueur
du paquet
Définir une socket par la classe DatagramSocket
Ce n’est pas fiable comme mode de communication!!
9
Imene Sghaier-Systèmes Répartis
10. SERVERSOCKET DU PACKAGE JAVA.NET
La classe ServerSocket denit une socket sur le
serveur.
Pour créer une ServerSocket, il faut lui donner un
numero de port.
Une fois créée, la socket Serveur attend une
connexion par la methode accept().
10
ServerSocket s = new ServerSocket(8888)
Socket socket = s.accept( ) ;
// attente d ' une connection
Imene Sghaier-Systèmes Répartis
11. SOCKET CLIENT PACKAGE JAVA.NET
Se connecter sur une socket d'un serveur, implique
de connaître son adresse.
InetAddress permet de récuperer une adresse à
partir d'un nom.
La liaison d'une socket à la socket serveur peut alors
être demandée.
11
InetAddress addr = InetAddress.getByName ( " poste1" ) ;
Socket socket = new Socket( addr , 8888) ;
Imene Sghaier-Systèmes Répartis
12. LA COMMUNICATION ENTRE SOCKETS
Les communications entre socket s'effectue
classiquement
par les flux d'entrées, issus de la méthode
getInputStream
par les flux de sorties, issus de la méthode
getOutputStream.
12
Imene Sghaier-Systèmes Répartis
16. EXEMPLE1
Le serveur est en attente de la part d'un client de la
création d'un socket:
16
Le serveur
attend sur le
port 9999 à son
adresse IP
le socket est
en attente
d'écriture du
client
Imene Sghaier-Systèmes Répartis
17. EXEMPLE1
Le client crée le socket
Le premier paramètre
est l'adresse IP du
serveur. On peut utiliser
:
"localhost",
Une adresse IP
"192.168.0.1",
Ou
InetAddress.getLocalHo
st() pour désigner l'IP
du serveur
17
Imene Sghaier-Systèmes Répartis
18. EXEMPLE2
Le serveur attend de multiples requêtes du client. Le
client envoie de multiples requêtes au serveur. Le client
ne reçoit pas de retour du serveur.
Dans ce cas le serveur doit boucler sur la lecture du
socket et le client doit boucler sur l'écriture du socket.
18
Imene Sghaier-Systèmes Répartis
21. EXEMPLE 3: CLIENT/SERVEUR
Un exemple classique de programmation
d’application distribuée: le client-serveur.
Un serveur est lance sur une machine et attend la
connexion d'un client.
Puis, il récupère les lignes envoyées par le client,
Il les affiche et les lui renvoie.
21
Imene Sghaier-Systèmes Répartis
24. LA SERIALISATION
La sérialisation consiste à pouvoir prendre un objet en
mémoire et à en sauvegarder l'état sur un flux de données
(vers un fichier, BD par exemple). Ce concept permettra aussi
de reconstruire, ultérieurement, l'objet en mémoire à
l'identique de ce qu'il pouvait être initialement.
La sérialisation peut donc être considérée comme une forme
de persistance des données.
La sérialisation se faisant sur un flux de données, elle est
utilisée pour écrire les données sérialisées sur un socket. Elle
est donc un moyen simple et efficace pour échanger des
données entre deux programmes informatiques.
Les formats de représentation de données sérialisées ont
beaucoup évolué afin de gagner en interopérabilité entre les
différents systèmes informatiques car un objet en mémoire ne
peut être échangé que entre deux systèmes compatibles
binairement (deux machines virtuelles Java).
Le format de sérialisation qui s'est largement répandu est le
XML.
24
Imene Sghaier-Systèmes Répartis
25. LA SÉRIALISATION EN JAVA
Dans le jargon des développeurs Java, sérializer un objet
consiste à le convertir en un tableau d'octets, que l'on peut
ensuite écrire dans un fichier, envoyer sur un réseau au travers
d'une socket etc...
Ce mécanisme existe depuis les débuts de l'API Java I/O, et il
est très pratique.
Il suffit de passer tout objet qui implémente
l'interface Serializable à une instance
de ObjectOutputStream pour sérialiser un objet. Si cet objet ne
comporte pas de champ trop exotique, comme des connexions à
des bases de données, des fichiers ou des threads, cette
sérialization se déroulera sans problème.
L'interface Serializable n'expose aucune méthode, implémenter
cette interface consiste donc juste à déclarer cette
implémentation.
25
Imene Sghaier-Systèmes Répartis
27. INTRODUCTION
Remote Method Invocation=pouvoir invoquer un objet d’une
JVM autre que la JVM locale. RMI permet la communication
entre machines virtuelles Java (JVM) qui peuvent se trouver
physiquement sur la même machine ou sur deux machines
distinctes.
RMI est un ensemble de classes permettant de manipuler des
objets sur des machines distantes (objets distants) de
manière similaire aux objets sur la machine locale (objet
locaux).
Le but de RMI est de permettre l'appel, l'exécution et le renvoi
du résultat d'une méthode exécutée dans une machine
virtuelle différente de celle de l'objet l'appelant..
27
Imene Sghaier-Systèmes Répartis
28. PRINCIPES RMI
La machine sur laquelle s'exécute la méthode
distante est appelée serveur.
L'appel coté client d'une telle méthode est un peu
plus compliqué que l'appel d'une méthode d'un objet
local mais il reste simple.
L’appel d’un Objet distant consiste à obtenir une
référence sur cet objet (instance) puis simplement
appeler la méthode à partir de cette référence.
La technologie RMI se charge de rendre transparente
la localisation de l'objet distant, son appel et le renvoi
du résultat.
28
Imene Sghaier-Systèmes Répartis
29. PRINCIPES RMI
En fait, elle utilise deux classes particulières, le
stub (souche) et le skeleton (squelette), qui doivent
être générées avec l'outil rmic fourni avec le JDK.
Le stub (souche) est une classe qui se situe côté
client et le skeleton est son homologue coté
serveur.
Ces deux classes se chargent d'assurer tous les
mécanismes d'appel, de communication,
d'exécution, de renvoi et de réception du résultat.
29
Imene Sghaier-Systèmes Répartis
30. PRINCIPES RMI
RMI assure la communication entre le serveur et le client via
TCP/IP,
RMI utilise des sockets et RMP (Remote Method Protocol).
Gestion de la securite par la classe RMISecurityManager
Gestion de la mémoire distribuée par le DGC (Distibuted Gabage
Collector).
30
Imene Sghaier-Systèmes Répartis
31. PRINCIPES RMI
Interfaçage : le client doit posséder une vue de ce qu'il peut
appeler : une interface décrivant ce qui est appelable chez
l'objet distant
Le client comme le serveur possède une copie de la même
interface
Seul le serveur possède une implémentation de l'interface
Si le client appelle une méthode distante, l'appel est
transmis à son "proxy"
RMI envoie la requête à l'implémentation côté serveur
Les valeurs de retour sont transmise au proxy client puis au
client
31
Imene Sghaier-Systèmes Répartis
32. PRINCIPES RMI
Utilisation de souches et squelettes générés à partir de
l’interface de l’objet.
Serveur d’objets : exécute les invocations d’objets de façon
multithread.
32
Imene Sghaier-Systèmes Répartis
33. PRINCIPES RMI
la couche souche contient des représentants
locaux de références d'objets distants. Une
invocation d'une fonctionnalité sur cet objet distant
est traité par la couche RRL (ouverture de socket,
passage des arguments, sérialisation, ...).
Les objets distants sont repérés par des références
gérées par la couche skeleton.
33
Imene Sghaier-Systèmes Répartis
34. CRÉATION D’UNE APPLICATION RMI
Pour créer une application RMI, il faut suivre les étapes
suivantes
1°) définir les spécifications du service RMI sous forme
d'interfaces.
2°) Créer et compiler les implémentations de ces interfaces.
3°) Créer les classes pour la souche et le skeleton à l'aide de
la commande rmic.
4°) Créer et compiler une application « lanceur du service RMI
».
5°) lancer le rmiregister et lancer l'application « lanceur du
service RMI ».
6°) Créer et compiler un programme client qui accède à des
objets distants : ce service RMI.
7°) lancer ce client. 34
Imene Sghaier-Systèmes Répartis
36. ETAPES POUR CRÉER UN OBJET DISTANT ET
L'APPELER AVEC RMI- COTÉ SERVEUR
Le développement coté serveur se compose de :
La définition d'une interface qui contient les méthodes qui
peuvent être appelées à distance
L'écriture d'une classe qui implémente cette interface
L'écriture d'une classe qui instanciera l'objet et l'enregistrera en
lui affectant un nom dans le registre de noms RMI (RMI
Registry)
36
Imene Sghaier-Systèmes Répartis
37. CRÉATION DE L’INTERFACE INTERFACE
L'interface à définir doit hériter de l'interface
java.rmi.Remote. Cette interface ne contient
aucune méthode mais indique simplement que
l'interface peut être appelée à distance.
L'interface doit contenir toutes les méthodes qui
seront susceptibles d'être appelées à distance.
La communication entre le client et le serveur lors
de l'invocation de la méthode distante peut échouer
pour diverses raisons telles qu'un crash du serveur,
une rupture de la liaison, etc ...
Ainsi chaque méthode appelée à distance doit
déclarer qu'elle est en mesure de lever l'exception
java.rmi.RemoteException. 37
38. CRÉATION DE L’INTERFACE INTERFACE
L'interface doit être présente chez le client et chez le
serveur
Les objets retournés doivent être Serializable
38
Imene Sghaier-Systèmes Répartis
39. CLASSE D’OBJET DISTANT IMPLÉMENTANT L’INTERFACE
Cette classe doit implémenter l'interface définie
Cette classe doit obligatoirement hériter de la classe
UnicastRemoteObject qui contient les différents traitements
élémentaires pour un objet distant dont l'appel par le stub du client est
unique.
Le nom de l'objet implémentant a pour suffixe Impl par convention
Le constructeur doit propager une exception RemoteException
39
Imene Sghaier-Systèmes Répartis
40. L'ÉCRITURE D'UNE CLASSE POUR INSTANCIER
L'OBJET ET L'ENREGISTRER DANS LE REGISTRE
Ces opérations peuvent être effectuées dans la méthode
main d'une classe dédiée ou dans la méthode main de la
classe de l'objet distant. L'intérêt d'une classe dédiée et
qu'elle permet de regrouper toutes ces opérations pour un
ensemble d'objets distants.
La marche à suivre contient trois étapes :
la mise en place d'un security manager dédié qui est facultative
l'instanciation d'un objet de la classe distante
l'enregistrement de la classe dans le registre de noms RMI
40
Imene Sghaier-Systèmes Répartis
41. LA MISE EN PLACE D'UN SECURITY MANAGER
Cette opération n'est pas obligatoire mais elle est
recommandée en particulier si le serveur doit charger
des classes récupérées sur des machines distantes.
Sans security manager, il faut obligatoirement mettre à
la disposition du serveur toutes les classes dont il aura
besoin (Elles doivent être dans le CLASSPATH du
serveur). Avec un security manager, le serveur peut
charger dynamiquement certaines classes.
Cependant, le chargement dynamique de ces classes
peut poser des problèmes de sécurité car le serveur
va exécuter du code d'une autre machine. Cet aspect
peut conduire à ne pas utiliser de security manager.
41
Imene Sghaier-Systèmes Répartis
42. LA MISE EN PLACE D'UN SECURITY MANAGER
42
Imene Sghaier-Systèmes Répartis
43. L'INSTANCIATION D'UN OBJET DE LA CLASSE
DISTANTE
1) Mise en place du Security manager
2) Instanciation de l’OD
43
Imene Sghaier-Systèmes Répartis
1
2
44. L'ENREGISTREMENT DANS LE REGISTRE DE NOMS RMI
La dernière opération consiste à enregistrer l'objet créé
dans le registre de noms en lui affectant un nom. Ce nom
est fourni au registre sous forme d'une URL constituée
du préfix rmi://,
du nom du serveur (hostname) et
du nom associé à l'objet précédé d'un slash.
Le nom du serveur peut être fourni sous forme d'une
constante chaîne de caractères ou peut être
dynamiquement obtenu en utilisant la classe InetAddress
pour une utilisation en locale.
C'est ce nom qui sera utilisé dans une URL par le client
pour obtenir une référence sur l'objet distant.
L'enregistrement se fait en utilisant la méthode rebind de la
classe Naming. Elle attend en paramètre l'URL du nom de
l'objet et l'objet lui-même.
44
45. L'ENREGISTREMENT DANS LE REGISTRE DE NOMS
RMI
La classe java.rmi.Naming:
L'enregistrement d’un un objet serveur se fait en utilisant la méthode
rebind de la classe Naming. Elle attend en paramètre l'URL du nom de
l'objet et l'objet lui-même.
diffuser des références à des objets d'un registre distant (comme
rmiregistry, JNDI (Java Naming and Directory Interface), ...).
avec adresse = "rmi ://host :port/nom" ou "//host/nom" ou nom est
le nom de l'objet dans l'annuaire et port constitue l’espace de
désignation => pas de transparence à la localisation.
bind(adresse, objet) : enregistre objet dans l'annuaire sous le nom de
l'adresse
rebind(adresse, objet) : enregistre un nouvel objet dans l'annuaire sous
nom déjà donne
unbind(adresse, objet) : désinscrit l'objet de l'annuaire sous l'adresse
donnée
list() : retourne tous les enregistrements d'objets
lookup(adresse) : retourne une référence à l'objet distant specifié dans
adresse 45
Imene Sghaier-Systèmes Répartis
48. ETAPES POUR CRÉER UN OBJET DISTANT ET
L'APPELER AVEC RMI
Le développement côté client se compose de :
L'obtention d'une référence sur l'objet distant à partir de
son nom
L'appel à la méthode à partir de cette référence
Enfin, il faut générer les classes stub (souche) et
skeleton (squelette) en exécutant le programme
rmic avec le fichier source de l'objet distant.
48
Imene Sghaier-Systèmes Répartis
49. LA MISE EN PLACE D'UN SECURITY MANAGER
Comme pour le coté serveur, cette opération est
facultative.
Le choix de la mise en place d'un sécurity manager
côté client suit des règles identiques à celles
appliquées côté serveur. Sans son utilisation, il est
nécessaire de mettre dans le CLASSPATH du client
toutes les classes nécessaires dont la classe stub.
49
Imene Sghaier-Systèmes Répartis
50. L'OBTENTION D'UNE RÉFÉRENCE SUR
L'OBJET DISTANT À PARTIR DE SON NOM
Il faut utiliser la méthode statique lookup() de la classe Naming.
Cette méthode attend en paramètre une URL indiquant le nom
qui référence l'objet distant. Cette URL est composée de
plusieurs éléments : le préfix rmi://, le nom du serveur (hostname)
et le nom de l'objet tel qu'il a été enregistré dans le registre
précédé d'un slash.
La méthode lookup() va rechercher l'objet dans le registre du
serveur et retourner un objet stub. L'objet retourné est de la
classe Remote (cette classe est la classe mère de tous les objets
distants).
Si le nom fourni dans l'URL n'est pas référencé dans le registre,
la méthode lève l'exception NotBoundException.
L'objet retourné étant de type Remote, il faut réaliser un cast vers
l'interface qui définit les méthodes de l'objet distant.
50
Imene Sghaier-Systèmes Répartis
52. EXEMPLE
Un exemple : calcul d’âge de personnes
Le client envoie un objet de classe Personne à un objet
distant qui calcule son âge c’est à dire retourne des
objets de classe Age.
On utilise donc deux classes :
Personne
Age
Ces deux classes doivent être sérialisables
52
Imene Sghaier-Systèmes Répartis
55. EXEMPLE
1ère Etape: définir les spécifications du service RMI à l’aide
d'interface.
Les classes placées à distance sont spécifiées par des
interfaces qui doivent
hériter de java.rmi.Remote
et dont les méthodes lèvent une exception
java.rmi.RemoteException.
=> On définit alors l’interface CalculAgeRMI.
55
Imene Sghaier-Systèmes Répartis
56. EXEMPLE
2ème Etape: Créer et compiler les implémentations
de ces interfaces.
Il s'agit d'écrire une classe qui implémente l’interface
CalculAgeRMI . C’est le service (classe) fourni à
distance.
Ces classes doivent dériver de
java.rmi.server.UnicastRemoteObject qui est la
classe qui permet de définir des objets distants
interrogeables à distance.
java.rmi.server.UnicastRemoteObject dérive de
java.rmi.server.RemoteObject qui redéfinit les
méthodes equals(), hashcode(), et les adaptent aux
objets distribués. 56
Imene Sghaier-Systèmes Répartis
58. EXEMPLE
Pour compiler utiliser les commandes :
javac -d classes business*.java
calculCalculAgeRMI*.java
58
Imene Sghaier-Systèmes Répartis
59. EXEMPLE
3 ème Etape: Créer les classes pour la souche et le
skeleton (commande rmic)
Il faut maintenant créer la souche et le skeleton pour
accéder aux classes ci dessus. Java donne un outil
rmic qui utilisent les fichiers .class.
la syntaxe de rmic est
rmic [options]
paquetage.sousPaquetage.nomDeClasse1
paquetage.sousPaquetage.nomClasse2...
On lance donc dans le répertoire ./classes :
rmic -d . calcul.CalculAgeRMIImpl
Seule la souche est créée. Le squeleton est devenu
inutile en Java 1.4. 59
Imene Sghaier-Systèmes Répartis
60. EXEMPLE
4ème Etape: Créer et compiler une classe qui créé
une instance du serveur RMI qui sera à l'écoute
des demandes des clients. Ce programme crée un
objet CalculAgeRMIImpl qui attend alors les
requêtes.
60
Imene Sghaier-Systèmes Répartis
62. EXEMPLE
Si on veut que l'application indépendante (lanceur de serveur
RMI) puisse télécharger des classes distantes (du futur client
RMI), il faut installer un SecurityManager spécifique. Celui-ci
est donné par Java et on l'installe par :
System.setSecurityManager(new
RMISecurityManager());
Pour rendre l'objet calcul de l’âge disponible, il faut l'enregistrer
dans le «RMIregistry ». On lui donne pour cela un nom et on
l'enregistre par la méthode statique
Naming.rebind(Constantes.NOM_OBJET_RMI, cmi);
Par la suite cet objet calculateur d’âge sera accessible par les
autres machines en indiquant la machine sur laquelle est
exécuté ce serveur RMI et le nom associé à cet objet.
Le premier argument de Naming.rebind() doit être une String :
On compile ce serveur par : javac -d classes
LanceServeurRMI.java 62
Imene Sghaier-Systèmes Répartis
63. EXEMPLE
5ème Etape: lancer rmiregister et l'application « lanceur de
serveur rmi »
Il faut d'abord lancer le rmiregister puis le serveur.
Sous Unix, on lance rmiregistry par : rmiregistry &
Sous Win32, on lance rmiregistry par : start rmiregistry
Il faut lancer rmiregistry dans un répertoire tel qu’il pourra accéder à
la souche lorsqu’on exécutera le « lanceur de serveur RMI ». En effet
ce lanceur de serveur RMI demande en fait au service de nommage
rmiregistry de connaître la souche (pour éventuellement la donner
aux clients par http).
Puis on lance le serveur : java LanceServeurRMI
Ce qui rend maintenant le serveur disponible pour de futurs clients.
Les sorties du serveur sont :
l'objet RMI est construit
l'objet RMI est inscrit au service de nommage
63
Imene Sghaier-Systèmes Répartis
64. EXEMPLE 2
6ème etape: Créer et compiler un programme client qui accède au serveur
RMI
Le programme doit être lancé par : % java ClientRMI localhost
64
Imene Sghaier-Systèmes Répartis
65. EXEMPLE 2
7 ème Etape: lancer ce client
java ClientRMI localhost
65
Imene Sghaier-Systèmes Répartis
66. TRAVAIL DEMANDÉ
Vous allez développer un serveur de chat à l’aide
de
L’API java.rmi
L’API javax.swing
66
Imene Sghaier-Systèmes Répartis