• Aucun résultat trouvé

Client RMI

N/A
N/A
Protected

Academic year: 2022

Partager "Client RMI"

Copied!
14
0
0

Texte intégral

(1)

I6 - Programmation Réseau

Programmation Client/Serveur

Java & RMI

Dernière minute...

Une petite remarque onernant la politique de séurité en Java pour le lanement des appliations

serveuretliente.

Vousremarquerezquel'unedespremièreslignesexéutéesdanslaméthodemaindesesappliationsest

setSeurityManager(...).Cette instrutionimposeà laJVM d'installer ungestionnaire de séurité pour

limiterle hamp d'ation de vosappliations. Du oup, pour qu'elles puissent s'exéuter "normalement", il

estnéessaired'indiqueràegestionnairedeséuritéquevosappliationsserveuretlienteontlapermission

d'établirdesonnexionsréseauxpourdialoguer.C'estquandmêmel'objetifdeeTP...;-)D'oùlanéessité

du hier java.poliy (page 7) et de l'option -Djava.seurity.poliy=java.poliy de la ommande

java.

Sivousne souhaitezpasêtre onfrontés auxproblèmes depermissionsinhérentsà lamiseen plaed'un

gestionnairedeséuritéenJava,ilvoussutsimplement demettreenommentaire(ou retirer)l'instrution

setSeurityManager(...)danslaméthodemaindevosappliationsserveuretliente.Peut-êtreaurez-vous

l'oasionde revenirun jour suresproblèmes de permissionsen lieneASUR...

(2)

I6 - Programmation Réseau

Programmation Client/Serveur

Java & RMI

Résumé

L'objetif de e premier TP est d'assurer la transition entre la programmation d'appliations mo-

noposte (un programme s'exéutant sur une mahine) et la programmation d'appliations distribuées

(plusieurs programmess'exéutantsur des mahines diérentes et interonnetésviale réseau). Ce TP

vous permettra de vous familiariser ave le modèle lient/serveur puis de le mettre en pratique sans

voussouierdesproblèmes inhérentsàlaouheréseau(programmationdessoketsnotamment).Nous

utiliseronspourelalesRMI(RemoteMethod Invoation)dulangageJava 1

.

1 Compléments de Cours

En POO et en Java vous avez déjà vu de quelle manière un objet (lient) pouvait invoquer une

méthode sur unautreobjet (serveur). Ils'agitde laversionla plussimpledumodèle lient/serveur

oùlesdeuxobjetss'exéutentsurlamême mahine.Leméanismed'invoationdeméthodesàdistane

de Java(les Java RMI) permet à un programme s'exéutant sur un ordinateur (lient) d'eetuer des

appelsde méthodessur unobjet setrouvantsur unordinateur distant (serveur).LesRMI orentainsi

aux programmeursJavala possibilitéde distribuer lestâhes exéutées par leursprogrammes dans un

environnement réseau. En oneption orientée objet, l'objetif est que haque tâhe soit exéutée par

l'objetleplusappropriépourettâhe.LesRMIvontenoreplusloindansettedémarheenpermettant

l'exéutiond'unetâhesurl'ordinateurleplusappropriéàette tâhe.

L'arhiteture RMI dénit un ensemble d'interfaes spéiques destinées à réer et manipuler des

objets distants. Un lient peut ainsi invoquer des méthodes sur un objet distant en utilisant la même

syntaxe quepour l'invoation de méthodes surun objet loal.L'API des RMI fournit les lasseset les

méthodesquivontgérertoutequionernelaouheommuniationsous-jaenteetlesréférenessurles

paramètreslorsdesinvoationsdeméthodesàdistane.LesRMIs'oupentégalementdelasérialisation

desobjetspassésenargumentsdesméthodessurlesobjetsdistants.

1.1 L'arhiteture RMI

Les paquettages java.rmi et java.rmi.serverontiennent les interfaes et les lasses qui implé-

mententtoutes esfontionnalités de l'arhitetureRMI. Ils ontiennentles briquesde base néessaires

pourdévelopperlesobjetsdutéserveuret lesobjets stubs dutélient.Un stub 2

est une représen-

tation loale del'objet distant.Le lient eetue sesinvoations deméthodes sur e stub (objet loal),

lequel s'oupe automatiquement de ommuniquer ave la partie serveur. Cei se fait de manièretota-

lement transparente pourlelient.Du téserveur,'est leskeleton 3

qui reçoitles appelseetués par

1

LesRMI(Remote Method Invoation)sontsimilairesauxRPC(Remote Proedure Call)introduitsparSUNen1985. Les

RPCnéessitaienttoutefoisdesérialisermanuellementlesparamètresetlesvaleursderetourdesméthodes.SUNavaitd'ailleurs

développéunebibliothèqueàeteet:XDR(eXternalDataRepresentation). Unedesprinipales diérenesentrelesRMIet

lesRPCestquelesRMIsebasentsurleméanismedesérialisationoertparlelangageJava.LesRMIpermettentégalement

desérialiserlesexeptionspouvantêtrelevéesparuneméthodedistantepourlestransmettreauxprogrammeslients.

2

La tradutionfrançaisede"stub"est"talon",e quiestmoinsparlant.Duoup,vousrenontrerezlaplupartdutemple

motstub,mêmeenfrançais.

(3)

ore, que l'invoation soit loale oudistante est totalementtransparentpourle serveur. Leprinipe de

fontionnementpeutserésumerainsi(f.gure1):

L'objet lient ne ommuniquepas diretement ave l'objet serveur, mais ave un proxy loal : le

stub.Celui-iestenhargede:

lasérialisationdesobjetspassésenparamètres(marshaling)

laonstrutiondelarequêteréseau

l'attentedurésultatset/oudesexeptions

Desonté,l'objetserveurest reliéauréseauviaunskeletondontlerleest de:

désérialiserlesparamètres(unmarshaling)

d'invoquerlaméthodesurl'objetserveur

desérialiserlerésultatset/oulesexeptionset delesrenvoyeraulientvialestub

Client RMI

Stub

Serveur RMI

Skeleton 1

2

3 4

5

6 7

RZO RZO

Fig. 1 Arhiteture RMI

Commeelaest illustréparlagure1,lorsquequ'unobjetlientinvoqueune méthodesurunobjet

serveurdistant,etteinvoationdeméthodedistantesedérouleenplusieursétapes:

1. l'objetlientinvoque(normalement)laméthodesurlestub

2. lestubsérialiselesobjetspassésenparamètresdel'appel(marshaling)puisenvoielarequêtesurle

réseau

3. le skeleton reçoit la requête, désérialise les paramètres (unmarshaling), puis invoque la "vraie"

méthodesurl'objetserveur

4. l'objetserveurexéute(normalement)laméthode

5. l'objetserveurretournelerésultatet/oulesexeptionsàl'objetayantinvoquélaméthode,'est-à-

direleskeleton(etnondiretementàl'objetlient)

6. leskeletonsérialiselerésultatet/oulesexeptions,puisenvoieletoutvialeréseauaustubquiavait

eetué larequête

7. lestubreçoitlerésultatdel'invoation,désérialiselesdonnées,puislestransmetàl'objet,omme

si l'invoationavait étéréaliséeloalement

Lestub n'est donqu'un proxypermettant àl'objet lient d'aédervialeréseau, et e demanière

totalementtransparente,auxservies (méthodes) proposés parl'objetserveur. Pouronstruire estub,

seule l'interfae duserveur est néessaire.C'est dans ette interfaeque le serveurdélare tousles ser-

vies qu'il propose. Il n'est pas néessaire de onnaître son implémentation. Quand on programme en

lient/serveurilestdonindispensabledebiendistinguerl'interfaeetl'implémentationduserveur.

1.2 Un exemple RMI pas à pas

Cettesetionvavousguiderpasàpasdanslaoneption,laompilationetl'exéutiond'unexemple

d'appliationutilisantlesRMI. Pourréeruneappliationqui soitaessibleàdeslientsdistants,vous

(4)

1. Dénirlesinterfaesdeslassesdistantes.

2. Erire etompilerl'implémentationdeeslassesdistantes.

3. Créerleslassesstub etskeletonenutilisantlaommandermi.

4. Erire etompilerl'appliationserveur.

5. Démarrer leRMIregistryetl'appliationserveur.

6. Erire etompilerleprogrammelientaédantauxobjetsdistants.

7. Testerlelient.

Nous allons détailler notre exemple en suivant les étapes indiquées i-dessus. L'exemple utilisé est

relativementsimple.L'appliationserveuresthargéedegérerplusieursomptesbanairesetdepermettre

à des programmes lients d'eetuerdiérentes opérations de base sur es omptes. Cet exemplea été

simpliéaumaximumandeseonentreruniquementsurlesRMI.

1.2.1 Interfaes des lasses distantes

Lapremièrelassequenousérivonsestellereprésentantunomptebanaire.Lesprogrammeslients

ne manipulerontpas diretement les objetsde ette lasse. Ils devront le fairevia la banque. Orette

dernièren'eetueraque desinvoationsdeméthodesloales.La lasse"omptebanaire"neseradon

jamais utilisée àdistane. Nous pouvons donérire l'interfae Compteet lalasse CompteImplomme

d'habitude.

Compte.java

import java.lang.*;

interfae Compte {

String nom();

double solde();

void deposer(double montant);

void retirer(double montant);

}

CompteImpl.java

import java.lang.*;

publi lass CompteImpl implements Compte {

// Attributs

private String _nom = null;

private double _solde = 0.0;

// Construteurs

publi CompteImpl()

{

_nom = "unknown";

_solde = 0.0;

}

(5)

{

this();

_nom = n;

}

// Méthodes de l'interfae

publi String nom()

{

return _nom;

}

publi double solde()

{

return _solde;

}

publi void deposer(double montant)

{

_solde += montant;

}

publi void retirer(double montant)

{

_solde -= montant;

}

}

Quandunprogrammelientvoudraréaliseruneopérationsurunomptebanaire,ildevras'adresser

à la banqueen indiquant leompte qu'ilveut manipuler.C'est donsur ette lasse "banque"que les

lientinvoqueront,àdistane,desméthodes.Lorsdeladénitiondel'interfaeBanquenousdevonsdon

indiquer qu'ils'agitd'une interfaedontles méthodespourrontêtre invoquées àdistane. Ilsut pour

ela qu'elle étende l'interfae java.rmi.Remote et que toutes ses méthodes signalent qu'elles peuvent

éventuellement lever une exeption java.rmi.RemoteExeption lors d'une invoation à distane. Ces

deux onditionssontimposées parl'utilitaire rmiqui sehargera de réerleslasses stub dutédes

lients.Cesstubsimplémenterontetteinterfae.

Banque.java

import java.lang.*;

interfae Banque extends java.rmi.Remote {

boolean existe(String nom) throws java.rmi.RemoteExeption;

void ouvrir(String nom) throws java.rmi.RemoteExeption;

double solde(String ompte) throws java.rmi.RemoteExeption;

void deposer(String ompte, double montant) throws java.rmi.RemoteExeption;

void retirer(String ompte, double montant) throws java.rmi.RemoteExeption;

void transferer(String ompte1, String ompte2, double montant)

throws java.rmi.RemoteExeption;

}

(6)

Nous pouvons maintenant érire l'implémentation de nos objets serveur. La lasse BanqueImplim-

plémentetoutnaturellementl'interfaeBanquedéniepréédemment.Commevouspouvezleremarquer,

nous indiquonsque la lasse BanqueImpl étendla lasse UniastRemoteObjet,e qui signie que les

objets intaniés à partir de la lasse BanqueImplne pourront traiter qu'une seule requête àla fois. Si

plusieurslientstententd'aéderenmêmetempsàundeesobjetsdistants,ilsserontmisdansunele

d'attente et nereevrontlaréféreneàetobjetdistantqu'unefoisette référenerelâhéeparlelient

préédent.

BanqueImpl.java

import java.lang.*;

import java.util.*;

import java.rmi.*;

import java.rmi.server.*;

// La lasse UniastRemoteObjet indique que l'objet

// distant sera "uniast", i.e. qu'il ne pourra répondre

// qu'à une seule requête à la fois.

publi lass BanqueImpl extends UniastRemoteObjet implements Banque {

// Attributs

private Hashtable _omptes = null;

// Construteurs

publi BanqueImpl() throws java.rmi.RemoteExeption

{

_omptes = new Hashtable();

}

// Méthodes de l'interfae

publi boolean existe(String nom) throws java.rmi.RemoteExeption

{

return ( (Compte)_omptes.get(nom) != null );

}

publi void ouvrir(String nom) throws java.rmi.RemoteExeption

{

_omptes.put(nom,new CompteImpl(nom));

}

publi double solde(String ompte) throws java.rmi.RemoteExeption

{

return ( (Compte)_omptes.get(ompte) ).solde();

}

publi void deposer(String ompte, double montant) throws java.rmi.RemoteExeption

{

( (Compte)_omptes.get(ompte) ).deposer(montant);

}

(7)

{

( (Compte)_omptes.get(ompte) ).retirer(montant);

}

publi void transferer(String ompte1, String ompte2, double montant)

throws java.rmi.RemoteExeption

{

( (Compte)_omptes.get(ompte1) ).retirer(montant);

( (Compte)_omptes.get(ompte2) ).deposer(montant);

}

}

LalasseBanqueImplestresponsable delaréationetdustokaged'objetsCompte.Elleutilise pour

elaune tabledehashagedontlalé estlenomduompte.

1.2.3 Création des lasses stub et skeleton

Unefoisquel'imlémentationdeslassesdistantessontompilées,l'étapesuivanteestlagénérationdes

lasses stub et skeleton permettant d'aéderàdistane àes distane. Les lassesstub serontutilisées

parleodedulientpourommuniqueraveleodeduskeletonduserveuronerné.

La ommande rmi permet de réer automatiquement le ode des stubs et skeletons à partir de

l'interfaeetdel'implémentationdeslassesdesserveurs.Parexemple,pourgénérerlestubetleskeleton

denotrelassedistanteBanque,ilfautexéuter:

rmi BanqueImpl

Cetteommandermiréedanslerépertoiredeuxnouveauxhiersdelasses,BanqueImpl_Skel.lass

etBanqueImpl_Stub.lass,orrespondantrespetivementauskeletonetaustubdelalasseBanqueImpl.

Les stubset lesskeletonsétantréés,l'étapesuivante onsisteàérirel'appliationserveur mettantes

lassesàdisposition deslientsdésirantyinvoquerdesméthodesàdistane.

1.2.4 Création et ompilation de l'appliation serveur

Toutest maintenantenplae pourledéveloppementde l'appliationtéserveur.Nous allonspour

elaréerunelasseServeurdontleseultravailserad'instanierunobjetàpartirdelalasseBanqueImpl

puisdelepublierdansleRMIregistryanqu'ilsoit aessibleparleslients.

Pardéfaut, lesappliations s'exéutentsansseuritymanager.L'appelsetSeurityManagerimpose

l'utilisationd'unRMIseuritymanager.Nousn'ironspasplusloinsurettenotion.Sahezsimplementque

eméanismepermet deséuriserlesonnexionslient/serveurenvériantnotammentquelesinterfaes

utiliséesparlelientsontbien ellespubliées parleserveur.Ceméanismepermetégalementl'envoide

esinterfaesàl'appliationlientesinéessaire.

Leserveurpublieensuitel'objetinstaniéenl'enregistrantdansleRMIregistrysousunertainnom.

Nousdisposonspoureladedeuxméthodes:bindetrebind.Cesdeuxméthodesfontionnentdemanière

identique,saufquandlenomestdéjàliéàunautreobjet.Danseas,laméthodebindlèveuneexeption

AlreadyBoundExeptionalorsque laméthode rebinddéréférenel'anien objet et fore le lien versle

nouvelobjet.Danslesdeuxas,lenomutiliséestunehaînedearatèresdelaformed'uneURL,'est-

à-dire protool ://host :port/bindingName.Dans leas présent, protoolorrespondà rmi, host

est le nom de la mahine sur laquelles'exéute le serveur RMI, port est le numéro de port sur lequel

le serveur est à l'éoute, et bindingName orrespond au nom exat qui sera utilisé par leslients pour

obtenirl'aèsauserveur.SiseullebindingNameestfourni,lesvaleurspardéfautsontutiliséespourles

autresparamètres,àsavoir:rmipourprotool,loalhostpourhostet 1099pourport.

(8)

import java.rmi.*;

publi lass Serveur {

publi stati void main(String args[℄)

{

// Création et installation d'un "seurity manager".

System.setSeurityManager(new RMISeurityManager());

try {

// Création d'une instane de notre lasse Banque

Banque bank = new BanqueImpl();

System.out.println("Banque réée");

// "Bind" de ette instane dans le RMI registry

Naming.rebind("banqueGTR",bank);

System.out.println("Banque enregistrée dans le RMI registry");

System.out.println("Le serveur est prêt...");

}

ath (Exeption e)

{

System.out.println("Il y a eu une erreur !!!");

e.printStakTrae();

System.out.println(e.getMessage());

}

}

}

1.2.5 Lanement du RMI registry et de l'appliation serveur

LeRMI registryest unprogramme qui permet defairela orrespondaneentre unnom symbolique

et uneréféreneversunobjetdistant(unobjetserveur).Commenousl'avonsvu préédemment,l'enre-

gistrementd'unnouvelobjet sefaitvialesméthodesbindet rebind.Lesappliations lientes pourront

alorsseonneterauRMIregistryetyfaireunlookupqui,àpartird'unnomsymbolique,instanieraun

stubet unskeletonpourleserveurindiqué,lesmettraenontat,puisretourneraaulientuneréférene

verslestub.

Les deux lignes de ommandes suivantes permettent d'intaller le RMI registrypuis de démarrer le

serveurbanaire.Pourdesraisonsde simpliation,nousnous abstiendronsdetéléhargerlesinterfaes

viaHTTP.Duoup,ilest néessaired'exéuterleRMIregistrydanslerépertoireoùsetrouventtoutes

leslassesquevousavezérites,demanièreàequ'ilpuisseyavoiraès.

rmiregistry

java -Djava.seurity.poliy=java.poliy Serveur

Commementionnépréédemment,nousnenousouponspaspourlemomentdesproblèmesdeséu-

ritéentreleserveuretlelient.C'estpouretteraisonquelapolitiquedeséuritéuiliséeestextrêmenent

simpleetpermissivepuisqu'elleautorisetouteslesonnexionsauxportssituésentre1024et65535,ainsi

qu'auport80(protooleHTTP).Cettepolitiqueestenregistréedanslehierjava.poliy.

grant {

permission java.net.SoketPermission "*:1024-65535", "onnet,aept";

permission java.net.SoketPermission "*:80", "onnet";

};

(9)

devriez obtenirei:

Banque réée

Banque enregistrée dans le RMI registry

Le serveur est prêt...

Anoter quevouspouvezdémarrer lermiregistrysur unportdiérent, equi est utilesiplusieurs

rmiregistrydoivent tourner simultanément sur lamême mahine. Ilsut pourela d'indiquer enpa-

ramètre le numéro du port (exemple : rmiregistry 2048). Ensuite, il vous faudra bien évidemment

signaler aux programmes serveurs et lientsqu'ils doivent utiliser e numéro de port pour ontater le

rmiregistryetnonleportpardéfaut(1099).

1.2.6 Création et ompilation du programme lient

Lorsque l'appliation liente démarre, elle doit trouver un objet Banque sur le serveur distant. Ce

programme suppose que le nom de la mahine sur laquelle s'exéute l'appliation serveur est passé

en premier argument sur la ligne de ommandes. Ce nom est utilisé pour réer une URL de la forme

rmi ://<hostname>/banqueGTR.CetteURLest passéeàlaméthode lookupinvoquéestatiquementsur

la lasse Naming.Comme indiquépréédemment, ette méthode renvoie au programme lient une réfé-

reneverslestub quisehargeradeommuniquer ave l'objetserveur.A noterqueletypederetourde

laméthodelookupestRemotequi estl'interfaemèredetouteslesinterfaesstubs.

Le programme lient utilise le seond argumentde sa ligne de ommandes omme nom de ompte

banaire.Ilontatealorsleserveurbanairepoureetuerplusieursopérationssureompte.

Client.java

import java.rmi.*;

publi lass Client {

publi stati void main(String args[℄)

{

Banque bank = null;

// Analyse des paramètres de la ligne de ommande

if (args.length < 2)

{

System.err.println("Usage:");

System.err.println("java Client <serveur> <nom ompte>");

System.exit(1);

}

// Création et installation d'un "seurity manager".

System.setSeurityManager(new RMISeurityManager());

// Obtention d'une référene de la banque (le serveur)

try {

String url = new String("//"+args[0℄+"/banqueGTR");

System.out.println("Client: lookup serveur, url = "+url);

bank = (Banque)Naming.lookup(url);

}

ath (Exeption e)

{

System.out.println("Erreur dans l'obtention du serveur"+e);

}

(10)

try {

// Si le ompte n'existe pas, on l'ouvre

if (!bank.existe(args[1℄))

{

bank.ouvrir(args[1℄);

System.out.println("Compte \""+args[1℄+"\" réé");

}

System.out.println("Le solde du ompte \""+args[1℄+"\" est de "+

bank.solde(args[1℄)+" FF");

bank.deposer(args[1℄,5000);

System.out.println("Ajout de 5000 FF sur le ompte \""+args[1℄+"\"");

System.out.println("Le solde du ompte \""+args[1℄+"\" est de "+

bank.solde(args[1℄)+" FF");

bank.retirer(args[1℄,400);

System.out.println("Retrait de 400 FF depuis le ompte \""+args[1℄+"\"");

System.out.println("Le solde du ompte \""+args[1℄+"\" est de "+

bank.solde(args[1℄)+" FF");

}

ath (Exeption e)

{

System.out.println("Erreur de transation pour "+args[1℄);

}

System.exit(0);

}

}

1.2.7 Test du programme lient

Ladernièreétapedenotreexempleonsisteàtesterlebonfontionnementdenotreprogrammelient

(etdonégalementdenotreappliationserveur).Ceprogrammepeutêtreexéutédepuisn'importequelle

mahineayantaèsauserveuretauxlassesnéessaires(nousutilisonspourlemomentunRMIseurity

managerminimal).Voiiunexempled'exéutiondeeprogrammeaveleserveurdistanttournantsurla

mahineurizen(lapremièreligneorrespondàlaommandeexéutée):

munierhryseis:remote > java -Djava.seurity.poliy=java.poliy Client urizen munier

Client: lookup serveur, url = //urizen/banqueGTR

Compte "munier" réé

Le solde du ompte "munier" est de 0.0 FF

Ajout de 5000 FF sur le ompte "munier"

Le solde du ompte "munier" est de 5000.0 FF

Retrait de 400 FF depuis le ompte "munier"

Le solde du ompte "munier" est de 4600.0 FF

Unefoisqueleprogrammelientaterminésonexéution,lesobjetsdistantsexistenttoujourssurle

serveur. L'exéution i-dessusa réé le ompte banaire pour l'utilisateur munier.Si nous exéutonsà

nouveaueprogrammeavelesmêmesparamètres,leprogrammevautiliserleompteexistant.Latrae

i-dessous montrebien quelesopérationsontété exéutéessur leomptedans l'étatoùil étaitaprèsla

premièreexéutionduprogrammelient.

(11)

Client: lookup serveur, url = //urizen/banqueGTR

Le solde du ompte "munier" est de 4600.0 FF

Ajout de 5000 FF sur le ompte "munier"

Le solde du ompte "munier" est de 9600.0 FF

Retrait de 400 FF depuis le ompte "munier"

Le solde du ompte "munier" est de 9200.0 FF

1.3 Sérialisation des paramètres

Dans l'exempleque nousvenonsde développer,lesparamètrestransmis lorsdesinvoationsde mé-

thodesàdistanesontdetypesrelativementsimples:double,String,...Imaginezmaintenantquevous

voulieztransmettredesparamètresplusompliquéstelsquedesobjetsinstanesdelassesquevousavez

dénies. Prenonsparexemplesleslassesreprésentantdesexpressionsnumériques(f.gure2).

Expression

double evaluer() String notationInfixee() String notationPostfixee()

Constante

double valeur

Fonction

Plus

Moins

Multiplier

Diviser

PlusU

MoinsU OperateurBinaire

Expression gauche Expression droite String opName()

OperateurUnaire

Expression expr

String opName() ?

Fig. 2 Graphe de lasses desexpressionsnumériques

Le problème est que pour pouvoir passer de tels objets omplexes en paramètres (nous parlons ii

d'arbres binaires dont les n÷uds peuventêtre de lasses diérentes), il est néessaire d'être apable de

lessérialiserdemanièreàlesdéouperenpaquetsauniveaudelaouheréseau,puisdereonstruirees

paramètressur lamahinedistante! Essayez delefairemanuellementpourvoir...et vousomprendrez

queen'estpassisimple;-)

Heureusement,Javaproposeenstandardunméanismedesérialisationautomatiquedeslasses.Ilvous

sutsimplementd'indiquerquel'interfaemèredevosparamètresétendl'interfaejava.io.Serializable

etletourestjoué.Parexemple:interfae Expression extends java.io.Serializable {...} Vous

pouvez bienévidemmentsurhargerlesméthodeswriteObjetetreadObjetutiliséeslorsdelasériali-

sation, maisellesdisponiblesenstandardsonttrèssatisfaisantes.

(12)

Ilestmaintenanttempspourvousdemettretoutesesnotionsenpratique.Voiidondeuxexeries

(distributeur de tikets,serveur DNS) qui, d'un point de vue algorithmique sont relativement simples,

maisquivouspermettrontjustementden'êtreonfrontésqu'àdesproblèmesd'invoationdeméthodessur

desobjetsdistants(parrapportauxinvoationsdeméthodes surdesobjetsloauxqui n'ontquasiment

plusauunseretpourvous).

2.1 Distributeur de tikets

Pour e premier exerie, il serait diile de faire plus simple. Il s'agit de réaliser un serveur ne

disposant qued'une seuleméthode : int prendreTiket().C'est le typede "serveur" que l'ontrouve

dansertainssupermarhésquandvousdevezfairelaqueuepourêtreservi(e):ildonneuntiketdiérent

àhaquefoisqu'onlesolliite.Ceserveurserainitialisélorsdesamiseenservie,puisdistribueraletiket

n

o 1

aupremierlient,letiket n

o 2

ausuivant,etainsidesuite.

Outrel'interfaeDistributeuretlalasseDistributeurImpl,vousdevrezégalementérireunpro-

gramme permettant de réer un nouveau serveur et de l'enregistrer dans le RMI registry ainsi qu'un

programmelientquiseonneteraàeserveurpourprendreuntiket.Ilvousfaudrabienévidemment

vérierquevousobtenezunnumérodetiketdiérentàhaqueappel.

2.2 Serveur DNS

Dans et exerie, onse propose pourela de réaliserl'interfaepuis l'implémentation d'un serveur

DNS (notéesrespetivementDNSetDNSImpl). Ceserveurpermettradefairelaorrespondaneentreun

nom demahine (uneString) etune adresseIP (pourlemoment, uneStringégalement).Ilproposeà

eteetdeuxservies:

Laméthodevoid enregistrer(String, String)permetaulientd'ajouterunenouvelleassoia-

tionnomde mahine/adresseIP dansleDNS.Lepremierparamètreest l'adresseIP,leseond est

lenom delamahine.

La méthode String reherher(String) reherhe l'adresse IP d'une mahine à partir de son

nom.

2.2.1 Objets loaux

Cettepremièrepartieestfaultative.Elleonsisteàérirel'interfaeDNS,lalasseDNSImplainsiqu'un

programme detest enonsidérantque touslesobjetss'exéutent surlamême mahine. Cettepremière

étapeorrespondàlaprogrammationorientéeobjetslassique.

2.2.2 Objets distants

Dans ette seonde partie vousallez testervos(nouvelles) ompétenes en programmation orientée

objetsdistribués.Ils'agitdemodierlesinterfaesetleslasseséritesdanslapremièreétapedemanière

à e que le serveur DNS puisse être utilisé par des programmes lients s'exéutant sur des mahines

diérentes.End'autrestermes,ilvousestdemandédemettreen÷uvreetdetesterlesméanismesRMI

pourlesméthodesenregistreret reherherduserveurDNS.

2.2.3 Objets distants & sérialisation

PouronlureetexeriesurlesRMI,nousvoulonshangerlareprésentationdesadressesIP.Aulieu

de stokersousformedehaînesdearatèresnous allonsdénirune interfaeAdresseIPet unelasse

AdresseIPImplpermettant dereprésenter une adresseIP sous laformed'un tableau dequatre entiers,

ave bien évidemmentlesméthodes adéquates.Lessignaturesdes méthodesduDNS doiventégalement

êtremodiées:

void enregistrer(AdresseIP, String)

AdresseIP reherher(String)

(13)

Maintenant quevousavez bien ompris leméanisme des RMI, nousallons passerà unexerie où

les invoations de méthodes à distane entre le "lient" et le "serveur" s'enhaînent les unes après les

autres. Vous allez pour ela développerun serveur hat auquel pourront se onneter plusieurs lients

pourdisuter.Le prinipedefontionnementest lesuivant:une fois leserveurdémarré,unlient peut

prendre partà la disussion en s'enregistrant sur le serveur, ei an de signaler saprésene. Ensuite,

lorsqu'un lientveutémettreunmessage,il l'envoieauserveur.A réeptiondee message,leserveurse

hargedeleretransmettreàtousleslientsquisesontenregistrés,quis'oupentalorsdel'ahersurla

onsoledel'utilisateur.Anquevouspuissiezutiliservotreprogrammelientaveleprogrammeserveur

d'un autre binme, le mieux est que vous vous basieztous sur lesmêmes interfaes(et e au aratère

prêt,yomprislesmajusules/minusules!).

ChatRoom.java

publi interfae ChatRoom extends java.rmi.Remote {

void enregistrerClient(ChatClient lient) throws java.rmi.RemoteExeption;

void envoyerMessage(Message msg) throws java.rmi.RemoteExeption;

}

ChatClient.java

import java.lang.*;

publi interfae ChatClient extends java.rmi.Remote {

String nom() throws java.rmi.RemoteExeption;

void affiherMessage(Message msg) throws java.rmi.RemoteExeption;

}

Message.java

import java.lang.*;

publi interfae Message extends java.io.Serializable {

String origine();

String toString();

}

Parlonsunpeuplusendétailsdelamanièredonttouteivafontionner.Eneet,ommevousallez

leonstaterrapidement,iln'existeplusdansetexeriede"lient"oude"serveur".Lesobjetsquenous

allonsutiliservontêtretouràtourlientouserveur;-)

1. Ondémarre,ommed'habitude,leRMIregistry.

2. On lane l'appliationserveurqui instanie unobjetChatRoom 4

puis l'enregistre,toujoursomme

d'habitude,dansleRMIregistry.

3. Onpeutalorsdémarreruneappliationlientesuruneautremahine. Celle-iseonneteauRMI

registrypourréupéreruneréféreneversl'objetChatRoom.Jusquelà,iln'yariendenouveaupar

rapportauxexeriespréédents.

4. C'estmaintenantqueçahangeunpeu.L'appliationlientepeutalorsinstanierunobjetChatClient.

Elle eetueensuiteune RMIpourinvoquerlaméthodeenregistrerClientsurl'objetChatRoom

enluipassantommeargumentlaréféreneversl'objetChatClientqu'ellevientderéer.

5. L'objetChatRoomstokeetteréféreneversl'objetChatClientdansundesesattributs(unVetor

parexemple).

6. L'appliationlienteentrealorsdansunboulequilitunehaînedearatèresaulavier,onstruit

unobjetMessage enpréisantsonnomomme origine,puisenvoie emessageàl'objetChatRoom

viauneRMIsurlaméthodeenvoyerMessage.

4

Ouplusexatementunobjetissud'unelasseimplémentantl'interfaeChatRoom.

(14)

objets ChatClient enregistrés et, pour haun d'entre eux, eetue à son tourune RMI sur leur

méthodeaffiherMessageenutilisanttoutsimplementlaréféreneChatClientstokée.Illuiest

inutiled'interrogerleRMIregistrypourfaireunlookuppuisquel'objetChatRoompossèdedéjàune

référeneversl'objetChatClientqu'ilveutatteindre(f.méthodeenregistrerClient).

8. Chaque objet ChatClientexéutera donsa méthode affiherMessagequi aura pour eet d'af-

herl'origineet leontenudumessagesurl'éran delamahinesur laquelle tournel'appliation

lienteorrespondante.

Dans e sénario, vous pouvez eetivement onstater qu'à l'étape 6, 'est l'objet ChatClient qui

eetueuneRMIversl'objetChatRoompourinvoquersaméthodeenvoyerMessage.L'objetChatClient

joue le rle de lient et l'objet ChatRoom joue le rle de serveur. Par ontre, à l'étape 7, 'est l'objet

ChatRoom qui eetue une RMI vers l'objet ChatClient pour invoquersa méthode affiherMessage.

Danse as,l'objetChatRoomjouelerledelientetl'objetChatClientjouelerledeserveur!

Uneonséquenedeeisetqu'ilvousseranéessairedegénérerlesstubsetlesskeletonsnonseulement

pourleslassesimplémentant l'interfaeChatRoom,mais égalementpourelles implémentantl'interfae

ChatClient,demanièreàequel'objetsChatRoompuisseinvoquerlaméthodeaffiherMessagesurdes

objetsChatClientdistants.

Références

Documents relatifs

JE JOUE À LA MAÎTRESSE Je joue à la maîtresse. Je joue à

²je ²joue du

[r]

[r]

On prépare 50 ballons pour la fête de l’école.. Malheureusement, 15

[r]

Comptine à prolonger Découvrir l’écrit Phonologie (rimes) Cycle

Être membre de l’AÉPQ, c’est soutenir votre association en lui donnant les moyens d’être au service de la communauté d’éducation préscolaire tout en s’engageant à….