Bertrand Dupouy et Frank Singhoff
Déroulement du TP :
Après avoir vu le fonctionnement élémentaire de RMI
on utilisera cet environnement pour mettre en place
un modèle client-serveur dans la première partie,
puis un modèle agents mobiles dans la deuxième partie.
Les fichiers nécessaires à ce TP
se trouvant
ici.
Pour les extraire, tapez la commande :
tar xvf tp-agents.tar
Environnement Java :
Pour éviter les problèmes de comptabilité entre
différentes versions de Java, il faut exécuter
un des scripts
agents.bash ou agents.tcsh.
Cette opération doit être effectuée avant de lancer javac, java,
rmiregistry ou rmic.
Par exemple, en tcsh, taper :
source agents.tcsh
(remarque : le fichier agents.bash est à l'intention
des utilisateurs de zsh et de bash.)
Pour cet exercice; placez vous dans le
répertoire EXO1.
On doit trouver les fichiers suivants :
ClientMagasin.java GerantMagasin.java Magasin.java
Mag1 Mag2 Mag3
Makefile README
MyHostName.java
Schéma du mécanisme d'interrogation :
Voici le contenu de l'interface Magasin.java :
public interface Magasin extends java.rmi.Remote
{
float RenvoyerPrix (String Ingredient) throws java.rmi.RemoteException;
}
GerantMagasin.java implémente cette interface :
public class GerantMagasin
extends UnicastRemoteObject implements Magasin
...
et ClientMagasin.java utilise la méthode publique
RenvoyerPrix.
ClientMagasin.java GerantMagasin.java Magasin.javaen faisant javac *.java
Les sources de ce dernier exercice se situent dans
le répertoire EXO2.
On doit trouver les fichiers suivants :
Agent.java Hote_implem.java Mag1 Mag3 Makefile
README initiateur java.policy MyHostName.java
threadAgent.java Hote.java Initiateur.java Mag2
Magasin.java agentIngredient.java java.env
lanceHote MySecurity.java
Les méthodes du fichier MySecurity.java surchargent les méthodes de
contrôle d'accès du Security Manager pour permettre le téléchargement
de code depuis un serveur httpd qui se trouve sur un site différent
de celui du serveur applicatif.
En effet, cette fois les fichiers .class (souches et agentIngredient.class) seront
récupérés par le client à l'aide d'un serveur httpd
qui est installé sur la machine 11de049.univ-brest.fr
Le schéma suivant indique les accès aux objets distants lors du lancement initial de l'agent :
Quand l'agent revient sur le site initiateur, on va y exécuter la méthode
migre. Sur ce site, la méthode migre
n'est pas implantée de la même façon que sur les
sites "Hote" :
Deux objets vont modéliser ces différents acteurs : Hote et Agent.
public interface Hote extends Remote { void migre(Agent a) throws RemoteException; }
Il y aura deux implémentations de cette interface Hote :
public interface Agent extends Serializable { void traitement(String [] ingredient, Float [] prix, int taille); String hoteSuivant(); void afficheResultat(); }
public class Hote_implem extends UnicastRemoteObject implements Hote ...
Les points importants du programme (Hote_implem.java), que l'on trouvera ici sont les suivants :
public class Initiateur extends UnicastRemoteObject implements Hote
Remarque importante :
le stub permettant l'accès aux méthodes proposées par un objet distant
est téléchargé lors de la recherche de cet objet par Naming.lookup.
Le téléchargement est fait par le serveur web donné par le paramètre
server.codebase défini au lancement du serveur qui
implémente l'objet distant.
Dans notre cas, Hote_implem_stub sera téléchargé lors
de l'exécution de la ligne suivante :
Hote hote = (Hote) Naming.lookup(name);
ce stub sera utilisé pour accéder à la méthode distante
migre pendant l'exécution de :
hote.migre(agent);
L'agent de notre application, appelé agentIngredient, est
implémenté à partir
de l'interface Agent, comme indiqué ci-dessous :
public class agentIngredient implements Agent {
public Float monPrix = new Float(Float.MAX_VALUE);
public String monIngredient="";
public String site="";
...
et dans le code de l'initiateur, on trouve :
agentIngredient agent = new agentIngredient
(Integer.parseInt(args[0])args[0],
hotes, args[1], args.length-2);
hote.migre(agent);
Le site qui exporte la méthode migre va créer un thread pour
gérer l'agent, comme on l'indique ici :
public void migre(Agent a)
{
threadAgent monThread = new threadAgent(a, monMagasin);
monThread.start();
}
la classe threadAgent hérite de thread :
class threadAgent extends Thread
java -Djava.rmi.server.codebase="http://11de049.univ-brest.fr:8080\ /$USER/tp-rmi/hosts/"\ -Djava.rmi.server.hostname=$HOST\ -Djava.security.policy=java.policy \ Hote_implem Mag1
server.codebase donne le nom du serveur web et du répertoire qui permettent aux appelants des méthodes distantes de télécharger les stubs correspondants (ici, il s'agit de Hote_implem_Stub.class). Cette information est associée à la référence de l'objet distant lors du bind par rmiregistry.
Attention :
le nom du serveur web ne doit pas être un alias, mais
le nom qualifié (par exemple : 011de049.univ-brest.fr) d'un site
qui détient réellement le répertoire.
De la même façon, pour lancer l'initiateur, on exécute
le script initiatieur:
java -Djava.rmi.server.codebase=...
-Djava.security.policy=java.policy
-Djava.rmi.server.hostname=$HOST
Initiateur $*
ici server.codebase
Complétez les fichiers suivants :
Les zones à compléter sont indiquées par des étoiles.
make clean make make installCes commandes compilent les sources et recopient les fichiers .class concernant le "client" et les "Hotes" dans le répertoire du serveur web. Les fichiers du serveur web sont dans le répertoire /home/commun_depinfo/enseignants/singhoff/APACHE/WEBPAGES/VOTRE_LOGIN ou VOTRE_LOGIN est le login Unix de la personne qui lance l'application.
cd /home/commun_depinfo/enseignants/singhoff/APACHE/LOGS more access_log
Exemple de trace des accès au serveur httpd par un utilisateur
dont le nom est tp :
Les serveurs ("Hote") tournent sur les machines
roxane, emma, quasimodo.
L'initiateur tourne sur la machine javert
et a été lancé ainsi :
initiateur 51000 sel roxane emma quasimodo
On voit tout d'abord les lancements successifs des serveurs ("Hote") :
roxane.univ-brest.fr ... "GET /singhoff/tp-rmi/hosts/Hote_implem_Stub.class HTTP/1.0" 200 1678
roxane.univ-brest.fr ... "GET /singhoff/tp-rmi/hosts/Hote.class HTTP/1.0" 200 252
emma.univ-brest.fr ... "GET /singhoff/tp-rmi/hosts/Hote_implem_Stub.class HTTP/1.0" 200 1678
emma.univ-brest.fr ... "GET /singhoff/hosts/Hote.class HTTP/1.0" 200 252
quasimodo.univ-brest.fr ... "GET /singhoff/tp-rmi/hosts/Hote_implem_Stub.class HTTP/1.0" 200 1678
quasimodo.univ-brest.fr ... "GET /singhoff/tp-rmi/hosts/Hote.class HTTP/1.0" 200 252
Puis on suit le lancement de l'initiateur :
javert.univ-brest.fr ... "GET /singhoff/tp-rmi/initiateur/Initiateur_Stub.class HTTP/1.0" 200 1676
javert.univ-brest.fr ... "GET /singhoff/tp-rmi/initiateur/Hote.class HTTP/1.0" 200 252
javert.univ-brest.fr ... "GET /singhoff/tp-rmi/hosts/Hote_implem_Stub.class HTTP/1.0" 200 1678
On suit également les accès des serveurs à l'agent,
puis au stub de l'initiateur :
roxane.univ-brest.fr ... "GET /singhoff/tp-rmi/initiateur/agentIngredient.class HTTP/1.0" 200 1848
emma.univ-brest.fr ... "GET /singhoff/tp-rmi/initiateur/agentIngredient.class HTTP/1.0" 200 1848
quasimodo.univ-brest.fr ... "GET /singhoff/tp-rmi/initiateur/agentIngredient.class HTTP/1.0" 200 1848
quasimodo.univ-brest.fr ... "GET /singhoff/tp-rmi/initiateur/Initiateur_Stub.class HTTP/1.0" 200 1676
©(Copyright)
dupouy@inf.enst.fr
singhoff@univ-brest.fr