Esercitazione di Laboratorio 5/12/2007
Sviluppare un applicazione RMI per la gestione di un elezione. Il server esporta un insieme di metodi: public void vota(string nome): accetta come parametro il nome del candidato. Non restituisce alcun valore. Registra il voto di un candidato in una struttura dati opportunamente scelta. public int risultato(string nome): accetta come parametro il nome di un candidato e restituisce i voti accumulati da tale candidato fino a quel momento. un metodo che consenta di ottenere i nomi di tutti i candidati, con i rispettivi voti, ordinati rispetto ai voti ottenuti.
Server
Server
Server
Server
Server
Server
Client
Client
Client
Client
Client
Server e Client: la Classe Candidato import java.io.serializable; public class Candidato implements Serializable private static final long serialversionuid = 1L; private String nome; private int voti; public Candidato(String nome) this.nome = nome; this.voti = 1; public String getnome() return this.nome; public int getvoti() return this.voti; public void vota() this.voti++; public String tostring() return nome + : + voti;
Server: l Interfaccia Remota Votazione import java.rmi.remote; import java.rmi.remoteexception; import java.util.arraylist; public interface Votazione extends Remote void vota(string nome) throws RemoteException; int risultato(string nome) throws RemoteException; ArrayList<Candidato> getcandidati() throws RemoteException;
Server: l Oggetto Remoto import java.rmi.registry.locateregistry; import java.rmi.registry.registry; import java.rmi.server.unicastremoteobject; import java.util.arraylist; import java.util.collections; import java.util.comparator; public class VotazioneServer implements Votazione private ArrayList<Candidato> candidati = new ArrayList<Candidato>(); public synchronized void vota(string nome) for(int i = 0; i < candidati.size(); i++) Candidato c = candidati.get(i); if(c.getnome().compareto(nome) == 0) c.vota(); return; candidati.add(new Candidato(nome));
Server: l Oggetto Remoto public synchronized int risultato(string nome) for(int i = 0; i < candidati.size(); i++) Candidato c = candidati.get(i); if(c.getnome().compareto(nome) == 0) return c.getvoti(); return 0; public synchronized ArrayList<Candidato> getcandidati() Collections.sort(candidati, new Comparator<Candidato>() public int compare(candidato c1, Candidato c2) return c2.getvoti() - c1.getvoti(); ); return candidati;
Server: il Main public static void main(string args[]) try VotazioneServer votazioneimpl = new VotazioneServer(); Votazione votazionestub = (Votazione) UnicastRemoteObject.exportObject(votazioneImpl, 0); Registry registry = LocateRegistry.getRegistry(); registry.rebind( votazione, votazionestub); System.out.println( Server ready ); catch(exception e)e.printstacktrace();
Client import java.rmi.registry.locateregistry; import java.rmi.registry.registry; import java.util.arraylist; public class VotazioneClient public static void main(string[] args) String host = localhost ; if(args.length > 0) host = args[0]; try Registry registry = LocateRegistry.getRegistry(host); Votazione stub = (Votazione) registry.lookup( votazione ); //si simulano tante votazioni in parallelo stub.vota( Berlusconi );stub.vota( Veltroni ); stub.vota( Veltroni );stub.vota( Veltroni ); stub.vota( Casini );stub.vota( Tremonti ); stub.vota( Veltroni );stub.vota( Fassino ); stub.vota( Fassino );stub.vota( Berlusconi ); stub.vota( Prodi );stub.vota( Berlusconi ); stub.vota( Bindi );stub.vota( Storace ); stub.vota( Berlusconi );stub.vota( Berlusconi ); stub.vota( Veltroni );stub.vota( Bertinotti );
Client System.out.println( Voti Berlusconi: + stub.risultato( Berlusconi )); System.out.println( Voti Fassino: + stub.risultato( Fassino )); System.out.println( Voti Casini: + stub.risultato( Casini )); System.out.println( Voti Veltroni: + stub.risultato( Veltroni )); System.out.println( ); ArrayList<Candidato> candidati = stub.getcandidati(); for(int i = 0; i < candidati.size(); i++) System.out.println(candidati.get(i)); catch(exception e)e.printstacktrace();
Esempio Sessione Server $ ssh user@fujim11.cli.di.unipi.it fujim11 [~] -> cd java/votazione/server/ fujim11 [~/java/votazione/server] -> ls *.java 4 Candidato.java 4 Votazione.java 4 VotazioneServer.java fujim11 [~/java/votazione/server] -> javac *.java fujim11 [~/java/votazione/server] -> rmiregistry & [1] 7534 fujim11 [~/java/votazione/server] -> java VotazioneServer Server ready
Esempio Sessione Client $ ssh user@fujim9.cli.di.unipi.it Password: fujim9 [~] -> cd java/votazione/client/ fujim9 [~/java/votazione/client] -> ls *.java 4 Candidato.java 4 VotazioneClient.java 4 Votazione.java fujim9 [~/java/votazione/client] -> javac *.java fujim9 [~/java/votazione/client] -> java VotazioneClient fujim11 Voti Berlusconi:5 Voti Fassino:2 Voti Casini:1 Voti Veltroni:5 Berlusconi:5 Veltroni:5 Fassino:2 Casini:1 Tremonti:1 Prodi:1 Bindi:1 Storace:1 Bertinotti:1
Modificare l esercizio precedente in modo che il server notifichi ogni nuovo voto ricevuto a tutti i client che hanno votato fino a quel momento. La registrazione dei client avviene nel momento del voto.
Callback: Osservazioni Per stabilire una connessione di callback RMI, devono essere fatte le seguenti estensioni: Il server deve avere una lista di client registrati. Il server ha bisogno di un metodo per permettere ai client di registrarsi e di de-registrarsi. Dato che i client devono chiamare questi metodo sul server, i metodi sono remoti: vota e unregisterclient. Visto che il client registrato deve poter essere chiamato da remoto, il client deve pubblicizzare i suoi metodi remoti, per cui deve avere un oggetto che implementa un interfaccia remota chiamabile dal server. L interfaccia è ClientCallbackInterface. Il metodo chiamabile è notify. Il client non ha bisogno di invocare rmiregistry. Infatti, il client quando invoca il metodo remoto per registrarsi passa un riferimento ad un oggetto remoto esportato dal client, per cui il server non ha bisogno di fare una lookup su quell oggetto visto che gli viene già passato. Il client, per terminare deve: (i) invocare la de-registrazione; (ii) fare l operazione inversa della export, per rimuovere l oggetto remoto dagli oggetti esportati (altrimenti il client rimane appeso e va terminato con CTRL+C).
Server
Client
Client
Client
Client
Client
Client
Client
Client
Server: l Interfaccia Remota Votazione import java.rmi.remote; import java.rmi.remoteexception; import java.util.arraylist; public interface Votazione extends Remote void vota(string nome, ClientCallbackInterface client) throws RemoteException; int risultato(string nome) throws RemoteException; ArrayList<Candidato> getcandidati() throws RemoteException; void unregisterclient(clientcallbackinterface client) throws RemoteException;
Server: l Oggetto Remoto import java.rmi.remoteexception; import java.rmi.registry.locateregistry; import java.rmi.registry.registry; import java.rmi.server.unicastremoteobject; import java.util.*; public class VotazioneServer implements Votazione private ArrayList<Candidato> candidati = new ArrayList<Candidato>(); private ArrayList<ClientCallbackInterface> clients = new ArrayList<ClientCallbackInterface>(); public synchronized void vota(string nome, ClientCallbackInterface client) if(clients.contains(client)) return; clients.add(client); for(int i = 0; i < candidati.size(); i++) Candidato c = candidati.get(i); if(c.getnome().compareto(nome) == 0) c.vota(); notifyclients(c); return; Candidato c = new Candidato(nome); candidati.add(c); notifyclients(c);
Server: l Oggetto Remoto private synchronized void notifyclients(candidato c) for(iterator<clientcallbackinterface> i = clients.iterator(); i.hasnext();) ClientCallbackInterface client = i.next(); try client.notify(c); catch(remoteexception e)system.out.println(e); public void unregisterclient(clientcallbackinterface client) clients.remove(client); public synchronized int risultato(string nome) for(int i = 0; i < candidati.size(); i++) Candidato c = candidati.get(i); if(c.getnome().compareto(nome) == 0) return c.getvoti(); return 0;
Server: l Oggetto Remoto e il Main public synchronized ArrayList<Candidato> getcandidati() Collections.sort(candidati, new Comparator<Candidato>() public int compare(candidato c1, Candidato c2) return c2.getvoti() - c1.getvoti(); ); return candidati; public static void main(string args[]) try VotazioneServer votazioneimpl = new VotazioneServer(); Votazione votazionestub = (Votazione) UnicastRemoteObject.exportObject(votazioneImpl, 0); Registry registry = LocateRegistry.getRegistry(); registry.rebind( votazione, votazionestub); System.out.println( Server ready ); catch(exception e)e.printstacktrace();
Client: l Oggetto Remoto import java.rmi.remote; import java.rmi.remoteexception; public interface ClientCallbackInterface extends Remote public void notify(candidato candidato) throws RemoteException; public class ClientCallbackImpl implements ClientCallbackInterface public void notify(candidato candidato) System.out.println( E stato votato: + candidato);
Client: il Main import java.rmi.registry.locateregistry; import java.rmi.registry.registry; import java.rmi.server.unicastremoteobject; import java.util.arraylist; public class VotazioneClient public static void main(string[] args) String host = localhost ; String nomecandidato = ; if(args.length > 1) host = args[0]; nomecandidato = args[1]; try Registry registry = LocateRegistry.getRegistry(host); Votazione stub = (Votazione) registry.lookup( votazione ); ClientCallbackImpl client = new ClientCallbackImpl(); ClientCallbackInterface callbackstub = (ClientCallbackInterface) UnicastRemoteObject.exportObject(client, 0); stub.vota(nomecandidato, callbackstub); Thread.sleep(25000); ArrayList<Candidato> candidati = stub.getcandidati(); for(int i = 0; i < candidati.size(); i++) System.out.println(candidati.get(i)); stub.unregisterclient(callbackstub); UnicastRemoteObject.unexportObject(client, true); catch(exception e)e.printstacktrace();
Esempio Sessione Server $ ssh user@fujim11.cli.di.unipi.it Password: fujim11 [~] -> cd java/votazionecallback/server/ fujim11 [~/java/votazionecallback/server] -> ls *.java 4 Candidato.java 4 ClientCallbackInterface.java 4 Votazione.java 4 VotazioneServer.java fujim11 [~/java/votazionecallback/server] -> javac *.java fujim11 [~/java/votazionecallback/server] -> rmiregistry & [1] 8160 fujim11 [~/java/votazionecallback/server] -> java VotazioneServer Server ready
Esempio Sessione Client in Parallelo Prima votazione: ssh user@fujim8.cli.di.unipi.it Password: fujim8 [~] -> cd java/votazionecallback/client/ fujim8 [~/java/votazionecallback/client] -> ls *.java 4 Candidato.java 4 ClientCallbackInterface.java 4 Votazione.java 4 ClientCallbackImpl.java 4 VotazioneClient.java fujim8 [~/java/votazionecallback/client] -> javac *.java fujim8 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Berlusconi E stato votato:berlusconi:1 E stato votato:veltroni:1 E stato votato:prodi:1 Berlusconi:1 Veltroni:1 Prodi:1 ssh user@fujim9.cli.di.unipi.it [...] fujim9 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Veltroni E stato votato:veltroni:1 E stato votato:prodi:1 Berlusconi:1 Veltroni:1 Prodi:1
Esempio Sessione Client in Parallelo ssh user@fujim5.cli.di.unipi.it [...] fujim5 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Prodi E stato votato:prodi:1 Berlusconi:1 Veltroni:1 Prodi:1 Seconda votazione: fujim8 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Casini E stato votato:casini:1 E stato votato:prodi:2 E stato votato:berlusconi:2 Berlusconi:2 Prodi:2 Veltroni:1 Casini:1 fujim9 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Prodi E stato votato:prodi:2 E stato votato:berlusconi:2 Berlusconi:2 Prodi:2 Veltroni:1 Casini:1
Esempio Sessione Client in Parallelo fujim5 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Berlusconi E stato votato:berlusconi:2 Berlusconi:2 Prodi:2 Veltroni:1 Casini:1 Terza votazione: fujim8 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Veltroni E stato votato:veltroni:2 E stato votato:veltroni:3 E stato votato:berlusconi:3 Berlusconi:3 Veltroni:3 Prodi:2 Casini:1 fujim9 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Veltroni E stato votato:veltroni:3 E stato votato:berlusconi:3 Berlusconi:3 Veltroni:3 Prodi:2 Casini:1 fujim5 [~/java/votazionecallback/client] -> java VotazioneClient fujim11 Berlusconi E stato votato:berlusconi:3 Berlusconi:3 \\ Veltroni:3 \\ Prodi:2 \\ Casini:1