import java.rmi.*;
public interface iCalendar extends Remote
{
java.util.Date dammiData() throws RemoteException;
}
// un’interfaccia serve a definire un prototipo di classe, senza nessuna
//implementazione
//========================= SERVER ==========================
import java.util.Date;
import java.rmi.*;
import java.rmi.registry.*;
import java.rmi.server.*;
public class CalendarImpl extends UnicastRemoteObject implements iCalendar
{
public CalendarImpl () throws RemoteException{} // costruttore vuoto
public Date dammiData()throws RemoteException
{
return new Date();
}
// impl. metodo del prototipo
public static void main(String s[])
{
CalendarImpl cal;
try {
LocateRegistry.createRegistry(1099); //crea una voce di registro
cal=new CalendarImpl();
Naming.bind("rmi:///CalendarImpl",cal); // collega alla voce di
//registro l’oggetto cal, rappresentante della classe CalendarImpl (per esportarlo)
System.out.println("Pronto per RMI");
} catch (Exception e) { e.printStackTrace(); }
}
}
//========================= CLIENT ==========================
import java.util.Date;
import java.rmi.*;
public class CalendarUser
{
public CalendarUser() {}
public static void main (String s[])
{
long t1=0, t2=0;
Date data1,data2;
iCalendar remoteCal;
try {
remoteCal =(iCalendar) Naming.lookup("rmi://x1/CalendarImpl");
data1=remoteCal.dammiData(); // invocaz. di un metodo remoto
t1=data1.getTime();
for (long i=1; i<90000000;i++);// perde un po’ di tempo
data2=remoteCal.dammiData(); // invocaz. di un metodo remoto
t2=data2.getTime();
} catch (Exception e) { e.printStackTrace(); }
System.out.println("Questa chiamata RMI ha richiesto la differenza tra
"+ t1+" e "+t2+" millisecondi, ossia "+(t2-t1));
}
}
La classe CalendarImpl crea ed esporta un oggetto remoto (un oggetto, cioè,
rappresentante di questa classe). L’esportazione è resa possibile da extends
UnicastRemoteObject e dalla registrazione e assegnazione al registro; inserendo
infatti un oggetto in registro, lo si rende disponibile per i client su altre
macchine (virtuali).
La classe CalendarUser cerca l’oggetto remoto in un registro e richiama il metodo
dammiData() definito per l’oggetto remoto.
Dopo aver inserito un oggetto in un registro, infatti, qualsiasi client può
ottenere un riferimento all’oggetto remoto specificando il nome della macchina, il
numero della porta (se diverso da quello predefinito, che vale 1099) e il nome
attribuito all’oggetto quando questo è stato messo nel registro.
Concludendo, CalendarImpl definisce l’implementazione dell’oggetto remoto. Un
oggetto date viene creato nel server (return new Date()) e una copia viene inviata
al client (data1=remoteCal.dammiData();). Il metodo dammiData() viene chiamato due
volte per vedere quanto tempo passa.
SERVER
CLIENT
scheletro
stub
Livello di comunicazione percepito
Livello di comunicazione effettivo
Quando un client richiama un metodo remoto, si ha l’illusione di richiamare
direttamente il metodo sull’oggetto remoto. In realtà la chiamata al metodo remoto
inizia come chiamata a un metodo locale in uno stub. Lo stub raggruppa in pacchetti
tutti i parametri e invia la richiesta allo scheletro dell’oggetto remoto; lo
scheletro suddivide i parametri inviati e inoltra la chiamata al metodo di
destinazione. Lo stub e lo scheletro sono responsabili di smistare i valori
restituiti.
SERVER (sulla macchina x1)
C:\>Dir ->(CalendarImpl.java, iCalendar.java)
C:\>javac CalendarImpl.java
C:\>rmic CalendarImpl
C:\>dir -> (CalendarImpl.java, iCalendar.java, CalendarImpl.class,
CalendarImpl_Stub.class, CalendarImpl_Skel.class)
C:\>copy CalendarImpl_Stub.class e iCalendar.java sul client
C:\>java CalendarImpl
Pronto per RMI
CLIENT
C:\>dir -> (CalendarUser.java, iCalendar.java, CalendarImpl_Stub.class)
C:\>javac CalendarUser.java
C:\>dir -> (CalendarUser.java, CalendarUser.class, iCalendar.java,
CalendarImpl_Stub.class)
C:\>java CalendarUser
Questa chiamata RMI ha richiesto la differenza tra 12345678500 e 12345678901
millisecondi, ossia 401