java rmi: remote method invocationdisys/rmi.pdf · rmi, deve essere dichiarata come tale indicando...
TRANSCRIPT
1
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Java RMI
I lucidi che seguono sono stati prodotti sulla base dei seguenti riferimenti: - Sistemi Distribuiti Dip. Informatica Università di Bari (S.Pizzutilo) - Seminario Java RMI di G.Cozzolongo
Java RMI: Remote Method Invocation
Java Remote Method Invocation (RMI) è l’implementazione Java del modello ad oggetti distribuiti
E’ un meccanismo che consente ad un oggetto su un JVM di invocare metodi di oggetti residenti in altre JVM
La sintassi per le invocazioni remote è esattamente la stessa di quella delle invocazioni locali Possono essere passati argomenti, calcolati nel contesto della
macchina chiamante Possono essere restituiti valori, calcolati nel contesto della macchina
remota Gli elementi chiave sono serializzazione e dynamic class loading
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Remote Method Invocation
Perche RMI? L’obiettivo è di permettere ad una applicazione in esecuzione su una macchina locale di invocare i metodi di un oggetto in esecuzione su un altro computer. Si definisce client il programma chiamante che ottiene riferimento all’oggetto remoto, server il programma che crea gli oggetti remoti. Tali applicazioni sono anche denominate distributed object application
• miglioramento delle prestazione complessive
• semplicità nella gestione delle risorse distribuite
• incremento della potenza operativa
es: suddivisione di una computazione pesante in procedure più piccole, eseguite tutte su macchine diverse diminuendo in tal modo il tempo complessivo di esecuzione
Quali vantaggi?
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
2
Terminologia di base
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Semantica invocazioni remote
• La semantica delle invocazioni remote non è uguale pero a quella delle locali...
• Infatti, i tipi primitivi (int, float,...) sono sempre passati per valore (semantica Call By Value, CBV)
• Il chiamato lavora una copia del tipo • Gli oggetti remoti sono sempre passati per riferimento (Call By Reference, CBR)
• Il chiamato riceve un riferimento all’oggetto
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Semantica invocazioni remote
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
3
Interface Definition Language
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Un client è dotato dell'interfaccia dei metodi disponibili sul server remoto, ma tutta l'implementazione è lasciata sul lato server. Nel programma client i dettagli dell'implementazione dei metodi remoti sono quindi invisibili.
Ciò che realmente collega il client e il server in un sistema RMI è una connessione stratificata, trasparente agli sviluppatori, effettuata dal sottosistema RMI delle due macchine virtuali coinvolte.
Transport Layer (Connessione TCP/IP)
Remote Reference Layer
Stub
Remote Reference Layer
Skeleton
Client (Interfaccia)
Server (Implementazione)
Architettura dell’RMI
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Stub: proxy locale su cui vengono fatte le invocazioni destinate all’oggetto remoto
Skeleton: elemento remoto che riceve le invocazioni fatte sullo stub e le realizza effettuando le corrispondenti chiamate sul server (ormai solo per back compatibility)
Remote Reference Layer:- -fornisce il supporto alle chiamate inoltrate dallo stub definisce e supporta la semantica dell’invocazione e della comunicazione
Transport Layer: localizza il server RMI relativo all’oggetto remoto richiesto, gestisce le connessioni (TCP/IP, timeout) e le trasmissioni (sequenziali, serializzate), usando Java Remote Method Protocol (JRMP).
Registry: servizio di naming che consente al server di pubblicare un servizio e al client di recuperarne il proxy
Componenti base dell’RMI
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
4
The Stub and Skeleton
A client invokes a remote method, the call is first forwarded to stub.
The stub is responsible for sending the remote call over to the server-side skeleton
The stub opening a socket to the remote server, marshaling the object parameters and forwarding the data stream to the skeleton.
A skeleton contains a method that receives the remote calls, unmarshals the parameters, and invokes the actual remote object implementation.
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
The General RMI Architecture
The server must first bind its name to the registry
The client lookup the server name in the registry to establish remote references.
The Stub serializing the parameters to skeleton, the skeleton invoking the remote method and serializing the result back to the stub.
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
The General RMI Architecture
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
5
Architettura di RMI
La struttura di un’applicazione RMI è organizzata in strati orizzontali sovrapposti
RMI Client
Stubs
Remote Reference Layer
Transport Layer
RMI Server
Skeleton
Remote Reference Layer
Transport Layer
Simulazione locale sul client
Oggetto reale eseguito sul server
Java Virtual Machine
Connessione fisica
Connessione virtuale
Il primo livello di questa connessione stratificata è rappresentato dagli stub (lato client) e gli skeleton (loto server) ai quali si riferiscono rispettivamente il client e il server senza occuparsi di ulteriori dettagli di più basso livello.
A loro volta, gli stub e gli skeleton demandano l'esecuzione di ciascuna attività allo strato immediatamente sottostante: il remote reference layer (RRL) che gestisce i riferimenti delle variabili agli oggetti remoti, usando la connessione TCP/IP del Transport layer sottostante.
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Architettura di RMI
Lo strato più alto è costituito da applicazioni (client e server) eseguite dalla Java Virtual Machine.
Lo stub e lo skeleton forniscono la rappresentazione dell’oggetto remoto: lo stub gestisce la simulazione locale sul client e, agendo come proxy, consente la comunicazione con l’oggetto remoto; lo skeleton invece consente l’esecuzione dell’oggetto remoto sul server.
Il client esegue i metodi dell’oggetto remoto in modo del tutto analogo alla chiamata locale:
ris = OggettoRemoto.nomeMetodo(par1, par2,..) senza preoccuparsi dei dettagli della comunicazione.
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
La serializzazione
Marshalling: processo di codifica di argomenti e risultati per la trasmissione.
Unmarshalling: processo inverso di decodifica di argomenti e risultati ricevuti.
In Java questo problema è risolto usando la serializzazione, che viene fatta in maniera trasparente dal supporto
Serializzazione: trasformazione di oggetti complessi in semplici sequenze di byte=> metodo writeObject() su uno stream di output
Deserializzazione: decodifica di una sequenza di byte e costruzione di una copia dell’oggetto originale=> metodo readObject() da uno stream di inputIn
Java sono utilizzati in molti casi: per memoria anche esterna trasmissione tra macchine diverse(parametri e valori di ritorno in RMI)
Esempio di storage http://lia.deis.unibo.it/Courses/cofimp/ Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
6
Il meccanismo alla base utilizzato da RMI per la trasmissione dei dati fra client e server è quello della serializzazione che permette il flusso di dati complessi all’interno di stream (può venir usata indipendentemente da applicazioni RMI)
• La serializzazione consiste nella trasformazione automatica di oggetti e strutture in sequenze di byte manipolabili coi vari stream del package java.io
• Gli stream sono associabili sia a socket che a file
es:
Record record = new Record()
ObjectOutputStream oos = new ObjectOutputStream(myos)
oos.writeObject(record);
La serializzazione
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
• Un oggetto è serializzabile se implementa l’interfaccia Serializable • Si possono serializzare oggetti con struttura e complessità arbitraria, senza particolari differenze, a patto che l’oggetto sia serializzabile (implementi cioè l’interfaccia Serializable) es: public class Record implements Serializable{ private String Nome; public Record(String Nome){this.Nome = Nome} }
• La serializzazione è ricorsiva ( un oggetto serializzabile deve contenere oggetti serializzabili) • La maggior parte delle classi del JDK è serializzabile (eccetto alcune che adottano strutture dati binarie dipendenti dalla piattaforma)
La serializzazione
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Passaggio parametri
Shallow Copy vs. Deep Copy considerando un grafo di oggetti
Passaggio per valore => Serializable Objects Passaggio per riferimento => Remote Objects
Oggetti serializzabili: Oggetti la cui locazione non è rilevante per lo stato. Sono passati per valore: ne viene serializzata l’istanza che sarà deserializzata a destinazione per crearne una copia locale.
Oggetti remoti: Oggetti la cui funzione è strettamente legata alla località in cui eseguono (server) Sono passati per riferimento: ne viene serializzato lo stub, creato automaticamente dal proxy (stub o skeleton) su cui viene fatta la chiamata in cui compaiono come parametri Sistemi Distribuiti Multiagente
A.A.2010-11 Informatica Magistrale Università di Bari
7
Gli stub: quali azioni fanno?
stub cliente: <ricerca del servitore> <marshalling argomenti> <send richiesta> <receive risposta> <unmarshallin grisultato> restituisci risultato fine stub cliente;
stub servitore: <attesa della richiesta> <unmarshalling argomenti> invoca operazione locale ottieni risultato <marshalling del risultato> restituisci risultato fine stub servitore;
In aggiunta, il controllo della operazione ed eventuali azioni di ritrasmissione (entro un tempo di durata massima)
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Stub e Skeleton
Stub e Skeleton sono oggetti generati dal compilatore RMI che gestiscono marshalling/unmarshalling e comunicazione (socket) tra client e server
Procedura di comunicazione: 1. Il client ottiene un’istanza dello stub 2. Il client chiama metodi sullo stub 3. Lo stub
a. crea una connessione con lo skeleton (o ne usa una già esistente) b. marshalling delle informazioni associate alla chiamata (id del metodo e argomenti) c. invia le informazioni allo skeleton
4. Lo skeleton a. unmarshalling dei dati ricevuti b. effettua la chiamata sull’oggetto chei mplementa il server c. marshalling del valore di ritorno e invio allo stub
5. lo stub: - unmarshalling del valore di ritorno erestituzione del risultato al client Sistemi Distribuiti Multiagente
A.A.2010-11 Informatica Magistrale Università di Bari
Passaggio di parametri
Qualsiasi classe, i cui oggetti devono essere trasmessi con una connessione RMI, deve essere dichiarata come tale indicando che deve implementare l'interfaccia java.io.Serializable.
Ogni parametro passato o ritornato da un metodo remoto deve essere o un oggetto di una classe primitiva Java, o un tipo di dato primitivo oppure un oggetto che implementa l'interfaccia java.io.Serializable.
Un client richiede al server un riferimento ad un oggetto usando lo stub sul lato client. Il server ottiene la richiesta dallo skeleton sul lato server.
Tra i due c'è il remote reference layer che negozia le richieste convertendo gli oggetti in un formato trasmissibile attraverso la rete. Questa conversione è chiamata marshalling. Se i dati da trasmettere non sono né primitivi né serializzabili, lo stub lancerà un'eccezione MarshalException.
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
8
Il passaggio dei parametri
Percorso dei parametri Serializzati dalla Virtual Machine Inviati sotto forma di stream al server Deserializzati del server che li utilizza all’interno del
corpo del metodo invocato Il risultato segue il percorso inverso fino ad arrivare al
client
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Gli strati RRL e TL
Il Remote Reference Layer (RRL) ha il compito di instaurare un connessione virtuale fra il client e il server ( esegue operazioni di codifica e decodifica dei dati). RRL adotta un protocollo generico e indipendente dal tipo di stub o skeleton utilizzato.
Il Transport Layer esegue la connessione vera e propria tra le macchine utilizzando le specifiche standard di networking di Java, e quindi le socket con il protocollo TCP/IP.
Si occupano della gestione “a basso livello” ( all’interno dell’architettura RMI) della comunicazione
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Il Transport Layer
Il TL è responsabile del controllo dello stato delle vari connessioni
I dati vengono visti come sequenze di byte da inviare o da leggere
IL TL si incarica di localizzare il server RMI relativo all’oggetto remoto richiesto
Esegue la connessione per mezzo di un socket
Le classi e i metodi sono contenuti nei package java.rmi e java.rmi.server
Si definisce oggetto remoto un oggetto che implementi l’interfaccia Remote i cui metodi possono essere eseguiti da un‘applicazione client posta su un’altra macchina virtuale
Programmare con RMI
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
9
Come trasformare un oggetto in un oggetto remoto?
public class MyServer{ public String concat (String a, String b){ return a+b; } } public interface MyServerInterface extend Remote{ public String concat (String a, String b)throws RemoteException; } public class MyServerImpl implements MyServerInterface extends UnicastRemoteObject{ public MyServerImpl() throws RemoteException{} public String concat (String a, String b)throws RemoteException{ return a+b;} } Sistemi Distribuiti Multiagente
A.A.2010-11 Informatica Magistrale Università di Bari
Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari
Hello World con RMI: definire l’applicazione
Di cosa ho bisogno? 1. Scrivere l’intefaccia dell’oggetto remoto :
MessageWriter.java 2. Scrivere il server che implementa l’interfaccia e la
rende accessibile : MessageWriterImpl.java da cui in seguito generare stub e skeleton
3. Scrivere il codice per la pubblicazione del server HelloServer.java
4. Scrivere il client che richiede l’accesso all’oggetto remoto : HelloClient.java
una volta definite le classi posso passare alla compilazione e posso lanciare la mia applicazione RMI…
Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari
Lanciare l’applicazione RMI
Una volta definite le classi (interfaccia, server, registrazione e client) posso compilare e lanciare il mio codice RMI.
Passi necessari: 5. Compilazione dei file .java 6. Generazione di stub e skeleton tramite il compilatore rmic 7. Avvio dell’RMI registry 8. Avvio dell’oggetto remoto (server) 9. Avvio del client
10
Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari
Hello World (1) Scrivere l’intefaccia dell’oggetto remoto : MessageWriter.java
L’interfaccia remota deve dichiarare tutti i metodi che si vuole poter richiamare in maniera remota deve essere dichiarata public deve estendere l’interfaccia java.rmi.Remote ogni metodo deve dichiarare java.rmi.RemoteException
nella sezione throws per proteggere l’applicazione da anomalie derivanti dall’utilizzo di risorse remote
//l’interfaccia dell’oggetto remoto import java.rmi.*;
public interface MessageWriter extends Remote {
String writeMessage(String s) throws RemoteException; }
Sistemi distribuiti A.A.2006-07 Informatica specialistica – Università di Bari
Hello World: (2) Scrivere il server (oggetto remoto) MessageWriterImpl.java
deve implementare almeno un’interfaccia remota deve definire i costruttori dell’oggetto remoto
deve fornire l’implementazione dei metodi invocati da remoto
creare e installare il security manager creare una o più istanza dell’oggetto
Implementare l’interfaccia remota
public class MessageWriterImpl extends UnicastRemoteObject implements MessageWriter { … }
• dichiara che implementa l’intefaccia MessageWriter ( con tutti i sui metodi)
• estende la classe UnicastRemoteObject per consentire la creazione di un oggetto remoto che
• adotta i protocolli di comunicazione di default di RMI basata sui socket e TCP
• rimane costantemente attivo Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
11
Definire i costruttori
il metodo super() chiama il costruttore della classe UnicastRemoteObject che esegue le inizializzazioni necessarie per consentire di rimanere in attesa (listen) di richieste remote su una porta e poterle gestire (accept)
potrebbe generare l’eccezione RemoteException se la connessione non fosse possibile
public MessageWriterImpl() throws RemoteException { super(); }
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Implementazione dei metodi remoti
devono essere implementati tutti i metodi dell’interfaccia
gli argomenti dei metodi e i risultati restituiti devono essere oggetti serializzabili
public String writeMessage(String s) throws RemoteException { return (s + " Ho ricevuto la tua stringa"); }
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Implementazione dell’oggetto remoto MessageWriterImpl.java
import java.rmi.*; import java.rmi.server.*; public class MessageWriterImpl extends UnicastRemoteObject implements
MessageWriter { public MessageWriterImpl() throws RemoteException { super(); } public String writeMessage(String s) throws RemoteException { return (s + " Ho ricevuto la tua stringa"); } }
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
12
Il security manager
Il metodo main deve creare e installare un security manager, che può essere il RMISecurityManager o definito in altro modo
Il S.M. garantisce che le classi che vengono caricate non eseguano operazioni per le quali non siano abilitate
se il S.M non è specificato non è permesso nessun caricamento di classi da parte sia del client ( stub ) che del server
if(System.getSecurityManager() == null){ System.setSecurityManager(new RMISecurityManager()); }
Chi garantisce che il codice scaricato da remoto non esegua operazioni pericolose?
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
HelloWorld (3) Scrivere il codice per la pubblicazione del server HelloServer.java
Nel metodo main si devono creare una o più istanze dell’oggetto che fornisce il servizio (oggetto remoto)
Una volta creato, l’oggetto è pronto per accettare richieste remote
import java.rmi.*;
public class HelloServer { public static void main (String args[]) throws Exception {
MessageWriterImpl messageWriter = new MessageWriterImpl(); Naming.rebind("myservice",messageWriter); //pubblicazione interfaccia
}
}
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Registrare l’oggetto remoto
Naming.rebind("myservice",messageWriter);
Il client deve poter ottenere un riferimento all’oggetto remoto:
RMI fornisce un registry degli oggetti per creare un’associazione (bind) fra un nome URL-formatted e un oggetto
l’RMI registry è un name-service che consente ai client di ottenere riferimenti agli oggetti: una volta registrato l’oggetto i client possono farne richiesta attraverso il nome e invocarne i metodi
nessun protocollo deve essere specificato nel primo argomento
la porta di default su cui risponde il RMIregistry è la 1099, ma può essere cambiata
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
13
Registrare l’oggetto remoto (2)
Un applicazione puo’ creare un’associazione solo sul RMIregistry del host locale
I client possono invece eseguire la propria ricerca di oggetti su qualunque host
L’operazione di registrazione può generare varie eccezioni AlreadyBoundException, se il nome logico è gia
utilizzato MalformedURLException, per errori nella sintassi
dell’URL RemoteException negli altri casi
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
RMI Registry
Problema di Bootstrapping: un client in esecuzione su un macchina ha bisogno di localizzare un server a cui vuole connettersi, che è in esecuzione su un’altra macchina.
Tre possibili soluzioni: - Il client conosce in anticipo dov’è il server - L’utente dice all’applicazone client dov’è il server (es. e-mail client) - Un servizio standard (naming service) in una locazione ben nota, che il client
conosce, funziona come punto di indirezione
Java RMI utilizza un naming service: - RMI RegistryMantiene un insieme di coppie {name, reference} - Name: stringa arbitraria non interpretata
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
HelloWorld (4) Scrivere il client che richiede l’accesso all’oggetto remoto : HelloClient.java
Deve ottenere un riferimento all’oggetto remoto che vuole richiamare dal RMIregistry eseguito sul server, utilizzando un’istanza dello stub a cui passare hostname ( ed eventualmente porta) e nome dell’oggetto
MessageWriter myWriter = (MessageWriter) Naming.lookup("myservice");
Richiama i metodi dell’oggetto secondo la sintassi solita String newstring = new String
(myWriter.writeMessage("Hello, world!")); System.out.println(newstring);
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
14
// il client per richiamare l’oggetto remoto Hello
import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.RMISecurityManager;
import java.rmi.*;
public class HelloClient { public static void main(String args[]) throws Exception { MessageWriter myWriter = (MessageWriter) Naming.lookup("myservice");
String newstring = new String (myWriter.writeMessage("Hello, world!")); System.out.println(newstring); } } Sistemi Distribuiti Multiagente
A.A.2010-11 Informatica Magistrale Università di Bari
(5) Compilazione
• Compilare i file .java col javac per creare i file .class.
• Generare stub e skeleton col comando rmic sul file che contiene l’implementazione dell’oggetto remoto (HelloImpl.class) rmic hello.MessageWriterImpl questo genera i file HelloImpl_Stub.class e HelloImpl_Skel.class NB: skeleton non è più in uso per le versioni della JVM successive alla 1.2
(6) Generazione di stub e skeleton
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
(7) Avvio dell’RMI registry
Lanciare in background RMIregistry col comando rmiregistry Questo processo utilizza per default la porta 1099
Lanciare il server - java HelloServer
Lanciare il client - Java HelloClient
(8) Avvio dell’oggetto remoto
(9) Avvio del client
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
15
Esempio: Calcolatrice con RMI
Implementazione dell’interfaccia
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface CalcolatriceServer extends Remote {
int addizione(int a, int b) throws RemoteException;
int sottrazione(int a, int b) throws RemoteException;
}
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Esempio: Calcolatrice con RMI Implementazione dell’oggetto remoto import java.rmi.*;
import java.rmi.server.*;
public class CalcolatriceServerImpl extends UnicastRemoteObject implements CalcolatriceServer { //implementazione del costruttore public CalcolatriceServerImpl() throws RemoteException{
super();
}
//implementazione dei metodi
public int addizione(int a, int b) throws RemoteException {
return a + b; }
public int sottrazione(int a, int b) throws RemoteException {
return a - b;
}
} Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Esempio: Calcolatrice con RMI Registrazione del server import java.rmi.Naming;
import java.rmi.*;
import java.rmi.server.*;
public class Registrazione {
public static void main(String args[]){
try {
CalcolatriceServerImpl obj = new CalcolatriceServerImpl();
Naming.rebind("calcolatrice", obj);
} catch (Exception e) {
e.printStackTrace();
}
}
} Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
16
Esempio: Calcolatrice con RMI
import java.rmi.Naming; import java.rmi.RemoteException; import java.util.InputMismatchException; import java.util.Scanner; public class CalcolatriceClient { public static void main(String[] arg){ try { CalcolatriceServer obj = (CalcolatriceServer) Naming.lookup("rmi://127.0.0.1/calcolatrice"); int risultato = 0; int scelta = 0; do {scelta = sceltaMenu(); switch (scelta) { case 1: System.out.println("addizione"); risultato = obj.addizione(1, 1); System.out.println ("1 + 1 = " + risultato); break; case 2: System.out.println("sottrazione"); risultato = obj.sottrazione(1,1); System.out.println ("1 - 1 = " + risultato); break; case 0: break; default: System.out.println("Errore, ripeti la scelta");break; } //end switch} while (scelta!= 0); } catch (Exception e) {e.printStackTrace();} }
public static int sceltaMenu(){ boolean valoreCorretto = true; int s = 0;
do{ Scanner input = new Scanner(System.in); System.out.println("Inserisci la tua scelta"); System.out.println("1 = addizione"); System.out.println("2 = sottrazione"); System.out.println("0 = exit"); try { s=input.nextInt(); valoreCorretto = false;} catch (InputMismatchException inputMismatchException) {input.nextLine(); // discard input so user can try again System.out.println("Scelta non valida. Inserisci un intero.\n");} } while (valoreCorretto); return s; }
}
Implementazione del Client
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Esempio:Implementare un Compute Engine
• Un compute engine è un oggetto remoto che consente ad un server di ricevere dei task dai client, eseguirli e restituire il risultato.
• Il task viene definito dal client ma viene eseguito sulla macchina del server.
• Il task può variare indipendentemente dal server, l’importante è che rispetti una determinata interfaccia
• Il compute engine scarica dal client il codice del task e lo esegue all’interno della propria Java virtual machine
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Interfacce utilizzate
Per implementare un compute engine servono due interfacce
• L’interfaccia Compute, che consenta ai client di inviare task all’engine
• L’interfaccia Task, che consenta all’engine di eseguire i task
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
17
Interfaccia Compute
package compute;
import java.rmi.Remote; import java.rmi.RemoteException;
public interface Compute extends Remote { Object executeTask(Task t) throws RemoteException; }
Questa intefaccia definisce i metodi che possono essere chiamati da altre virtual machine. Gli oggetti che implementano questa interfaccia diventano oggetti remoti.
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Interfaccia Task
package compute;
import java.io.Serializable;
public interface Task extends Serializable { Object execute(); }
Questa interfaccia è usata come argomento nel metodo executeTask dell’interfaccia Compute (definito precedentemente) e fornisce al Compute Engine il meccanismo per eseguire il task. Non è un interfaccia remota, quindi non è associata ad oggetti remoti.
Il metodo execute deve essere presente in ogni implementazione di questa interfaccia. Sistemi Distribuiti Multiagente
A.A.2010-11 Informatica Magistrale Università di Bari
//oggetto remoto per l’esecuzione dei task package engine;
import java.rmi.*; import java.rmi.server.*; import compute.*;
public class ComputeEngine extends UnicastRemoteObject implements Compute { public ComputeEngine() throws RemoteException { super(); } public Object executeTask(Task t) { return t.execute(); }
// metodo main }
Implementazione del Compute Engine
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
18
public static void main(String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); }
String name = "//host/Compute"; try { Compute engine = new ComputeEngine(); Naming.rebind(name, engine); System.out.println("ComputeEngine bound"); } catch (Exception e) { System.err.println("ComputeEngine exception: ” + e.getMessage()); } }
Metodo main del ComputeEngine
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
package client; import java.rmi.*; import java.math.*; import compute.*; public class ComputePi { public static void main(String args[]) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMIS...()); } try { String name = "//" + args[0] + "/Compute"; Compute comp = (Compute) Naming.lookup(name); Pi task = new Pi(Integer.parseInt(args[1])); BigDecimal pi = (BigDecimal) (comp.executeTask(task)); System.out.println(pi); } catch (Exception e) { System.err.println("ComputePi exception: " + e.getMessage()); }}}
Implementazione del client
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Implementazione dell’interfaccia Task package client;
import compute.*; import java.math.*;
public class Pi implements Task { /** costante usata nel calcolo di pi */ private static final BigDecimal ZERO = BigDecimal.valueOf(0); /** ...... ...... **/ public Pi(int digits) { this.digits = digits; } /*** Calcola pi.*/ //Poiché implementa l’interfaccia Task deve esserci questo public Object execute() { return computePi(digits); } public static BigDecimal computePi(int digits) { ...... } } Sistemi Distribuiti Multiagente
A.A.2010-11 Informatica Magistrale Università di Bari
19
Riassunto degli elementi necessari
Due interfacce : compute.java task.java
Il server che implementa l’interfaccia compute e comprende il metodo main per l’esecuzione: ComputeEngine.java
L’implementazione del task da far eseguire: Pi.java Il client che richiede l’esezuzione del task al server:
ComputePi.java
In più vengono generati i file per lo stub e lo skeleton: ComputeEngine_stub.java ComputeEngine_skel.java
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Esercizio
Provate a svolgere l’esercizio precedente (calcolatrice)
secondo modello illustrato per un generico Compute Engine
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
Altro esempio interessante dal web…
http://lia.deis.unibo.it/Courses/cofimp/
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari
20
Oltre a RMI per l’esecuzione remota
RPC (Remote Procedure Call): rende possibile
gestire procedure facenti parte di applicazioni
remote rispetto al chiamante
utilizzate soprattutto nei sistemi UNIX
non si inseriscono nel contesto della
programmazione ad oggetti
DCOM (estensione di COM di Microsoft )
CORBA (Common Object Request Broker
Architecture)
Sistemi Distribuiti Multiagente A.A.2010-11 Informatica Magistrale Università di Bari