Matteo Baldoni
Dipartimento di Informatica - Universita` degli Studi di Torino C.so Svizzera, 185 - I-10149 Torino (Italy)
e-mail: [email protected] - URL: http://www.di.unito.it/~baldoni
Linguaggi di
Programmazione: Paradigmi di Programmazione
Socket, Servlet e
Remote Method Invocation
Architettura Client/Server
Un servizio presso un computer- server è identificato dai seguenti valori:
• IP (32 bit)
• Port (16 bit)
Alcuni tipici servizi:
• telnet
• http
• ftp
• SMTP, IMAP4
• NFS, DNS, NIS, ...
IP Address IP Address
IP Address
Servizi telnet ftp
http TCP IMAP
TCP
TCP Server
Client
Client
Client
Socket, Servlet e Remote Method Invocation 3
Socket
• È una astrazione software che rappresenta il terminale di una connessione tra due computer
• Per ogni connessione esiste un socket in ognuno dei computer coinvolti
• Il client effettua la richiesta di una connessione ad un server per un servizio collegato ad una determinata porta
• Se la richiesta è accettata la connessione tra i due applicativi dei due computer è stabilita
IP Address
IP Address
Port
Port
TPC Server
Client
Socket:
<IP Client, Port Client, IP Server, Port Server>
Socket:
<IP Client, Port Client, IP Server, Port Server>
4
Socket e Stream in Java
• Da ogni socket
e`possibile ottenere uno stream di input ed uno di output
• Lúso dei socket
e`trasparente: readLine e println
BufferedReader
in = new BufferedReader(
new InputStreamReader(
socket.getInputStream()));
PrintWriter
out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream())),
true); Abilita il flush immediato
Socket, Servlet e Remote Method Invocation 5
Socket in Java
• Package da importare java.net
• La classe java.net.Socket implementa un
“client socket”
– richiede l’indirizzo IP e il numero della porta del servizio a cui vogliamo connetterci
• La classe java.net.ServerSocket implementa un “server socket”
– richiede il numero della porta a cui vogliamo associare il servizio
– crea un “server” che attende le richieste di connessione
– restituisce un socket nel momento in cui accetta un collegamento completamente istanziato nei parametri di collegamento (IP e Porta locale e remota).
IP Address
IP Address
Port
Port TPC
Server
Client Socket ServerSocket
ServerSocket
• Il metodo accept() si mette in attesa di una richiesta di connessione da un socket client
• Le eccezioni che possono essere sollevate sono del tipo IOException (da catturare e gestire!)
IP Address
Port Server
ServerSocket
ServerSocket s = new ServerSocket(PORT);
[…]
Socket socket = s.accept();
System.out.println("Accettato socket " + socket);
[…]
socket.close();
Crea un nuovo socket sul server per accettazione di una richiesta di
connessione
Chiude il socket di una connessione precedentemente accettata
Socket, Servlet e Remote Method Invocation 7
Socket (Client)
• Crea una connessione con un’applicazione server (in attesa in una accept()) e restituisce il relativo socket
• Le eccezioni che possono essere sollevate sono del tipo IOException (da catturare e gestire!)
IP Address Port
Client Socket Socket socket = new Socket(IP, PORT);
[…]
socket.close();
E`un valore intero, in genere non inferiore a 1024 (riservati al sistema) e rappresenta il numero della porta a cui Vogliamo connetterci
E`un oggetto del tipo
java.net.InetAddress contenente l’indirizzo IP della macchina a cui vogliamo connetterci ad esempio speedy/130.192.241.1
8
ServerSocket e Socket:
gestione errori
• E`importante che i socket siano propriamente chiusi al termine di
un’applicazione in quando questi sono una risorsa di rete condivisa del sistema
• La chiusura dei socket deve essere eseguita
indipendentemente dal flusso di esecuzione per questo e`bene utilizzare il costrutto try-finally per garantirne la chiusura
• La stessa considerazione vale anche per il
ServerSocket
[…]
try { […]
String str = in.readLine();
[…]
out.println("OFFERTA");
[…]
}
catch(IOException e) {
System.err.println("IO Exception" + e);
} finally { try {
socket.close();
} catch(IOException e) {
System.err.println("Socket not closed");
} } […]
try {
Socket socket = s.accept();
[…]
} finally { s.close();
}
Socket, Servlet e Remote Method Invocation 9
Un esempio: l’asta
• Il server è il banditore: accoglie le offerte e comunica se sono accettabili o no, comunica a richiesta la migliore offerta corrente
• I client sono i partecipanti all’asta, possono richiedere qual’è la migliore offerta (e di chi) e possono effettuare rilanci se il loro budget a disposizione lo consente
Un esempio: l’asta
• Un thread per ogni partecipante all’asta
• L’offerta è rappresentata da un oggetto che contine l’offerente e l’offerta in denaro
• La migliore offerta è memorizzata in un oggetto il cui accesso è effettuato mediante un metodo synchronized
• Per trasmettere un’offerta è necessario convertirla in una stringa (encode)
• Il server ricostruisce dalla stringa ricevuta
un’offerta (decode)
Socket, Servlet e Remote Method Invocation 11
Stream di oggetti e Socket
• Nell’esempio dell’asta i dati di una offerta venivano opportunamente codificati in una unica stringa per essere trasferiti da un client ad un server
• In Java si puo`pero`
utilizzare anche stream di oggetti (ObjectInputStream e OutputObjectStream)
• In Java e`possibile utilizzare stream di oggetti tramite socket
• Gli oggetti devono
implementare l’interfaccia java.io.Serializable
IP Address
IP Address
Port
TPC Port
Server
Client
Anche stream di oggetti…
E` importante che possano essere serializzati
12
Stream di oggetti e Socket
• Importante: la dichiarazione nel client è analoga MA è l’oggetto di tipo ObjectOutputStream va creato prima dell’oggetto di tipo ObjectInputStream pena il deadlock (non è un bug!)
• Il polimorfismo viene preservato (si preserva il vero tipo dell’oggetto)
[…]
ServerSocket s = new ServerSocket(PORT);
[…]
Socket socket = s.accept();
[…]
ObjectInputStream in =
new ObjectInputStream(socket.getInputStream());
ObjectOutputStream out =
new ObjectOutputStream(socket.getOutputStream());
[…]
Offerta nuova = (Offerta)in.readObject();
[…]
out.writeObject("accettata");
[…]
Server
Socket, Servlet e Remote Method Invocation 13
Servlet e Web Server
Servlet:
• estensioni del Java API
• permettono di scrivere applicazioni indipendenti eseguite all’interno del Web server
• possono servire richieste in parallelo
• mantengono la sessione di lavoro con il singolo utente
• efficienti e semplici da utilizzare rispetto ai programmi CGI
Servlet e Web Server
Web Server Client Browser
Java Virtual Machine
Servlet
HttpServletResponse HttpServletRequest
Socket, Servlet e Remote Method Invocation 15
Servlet e Web Server
• Una servlet è una classe Java (estensione di HttpServlet).
• Un Web Server può ospitare più servlet (con relativi alias)
• Quando il processo Web Server viene lanciato, genera un thread Java che inizializza l’oggetto Servlet (metodo init), questo persiste per tutta la durata per processo Web Server
• Ogni servlet è un thread all’interno del Web Server (vs CGI dove viene eseguito un processo esterno)
16
Servlet
• Ogni volta che il Web Server riceve una richiesta per una servlet S:
– identifica la servlet S
– invoca il metodo service dell’oggetto Servlet S, per far eseguire le operazioni richieste
• Il metodo service rappresenta l’interfaccia del secondo livello di applicazione. Al termine del metodo, S rimanda una risposta sotto forma di pagina HTML
• Il Web server spedisce la pagina al browser
chiamante
Socket, Servlet e Remote Method Invocation 17
Richieste
ES: http://nbbaldoni.di.unito.it/servlets/splppp0001.Re gistration?cognome1=Baldoni&nome1=Matteo
• La classe HttpServletRequest offre i metodi per – determinare i parametri di una richiesta
(cognome1, nome1)
– estrarre i valori speficati per i parametri nella richiesta (Baldoni, Matteo)
• metodi gestiti: POST (doPost), GET (doGet)
Servlet e Web Server
• Apache, Netscape, Microsoft o Oracle Web Server
• le servlet erano inizialmente solo integrate nel Java Web Server della Sun
• JSP: Java Server Pages, analogo di ASP (Active Server Pages), progetto Tomcat
• Modulo ApacheJServ
Socket, Servlet e Remote Method Invocation 19
Un esempio:
Registration.java
• Analizzare le informazioni dei componenti di un gruppo inserite tramite una form ed inviate mediante il metodo POST
• Se non sono rilevati errori spedire una mail con il numero del gruppo (assegnato in modo
automatico) e spedire le varie infomazioni raccolte tramite mail
• Se sono rilevati errori nell’immissione dei dati nella form segnalarli tramite una pagina html
20
registration.html
<FORM ACTION="https://nbbaldoni.di.unito.it/servlets/splppp0001.Registration"
METHOD="post”>
[…]
<INPUT TYPE="text" NAME=cognome1 VALUE="" SIZE=40>
[…]
<INPUT TYPE="text" NAME=nome1 VALUE="" SIZE=40>
[…]
<INPUT TYPE="text" NAME=email1 VALUE="" SIZE=40>
[…]
<INPUT TYPE="text" NAME=cognome2 VALUE="" SIZE=40>
[…]
<INPUT TYPE="text" NAME=nome2 VALUE="" SIZE=40>
[…]
<INPUT TYPE="text" NAME=email2 VALUE="" SIZE=40>
[…]
<TEXTAREA NAME=commenti COLS=50 ROWS=5></TEXTAREA> <br>
[…]
<INPUT TYPE="submit" VALUE="Inoltra">
<INPUT TYPE="reset" VALUE="Cancella">
</FORM>
Socket, Servlet e Remote Method Invocation 21
Registration.java
public class Registration extends HttpServlet { […]
int counter;
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html");
PrintWriter out = res.getWriter();
[…]
}
Viene utilizzato sia per l’invio con POST sia con GET
MIME type della risposta
PrintWriter per l’output
Registration.java
[…]
HTMLPage page = new HTMLPage();
[…]
String cognome1 = req.getParameter("cognome1").trim();
String nome1 = req.getParameter("nome1").trim();
String email1 = req.getParameter("email1").trim();
[…]
int localCounter;
synchronized(this) {
localCounter = counter++;
saveState();
} […]
Attenzione questa classe l’ho definita io per facilitare la creazione di una pagina HTML
Estrazione dei parametri inviati alla servlet dalla form
Incremento del contatore per il numero del gruppo counter è una variabile condivisa dai vari thread delle diverse richieste della stessa servlet
Socket, Servlet e Remote Method Invocation 23
Registration.java
public void init(ServletConfig config) throws ServletException { super.init(config);
try {
FileReader fileReader =
new FileReader("/tmp/InitDestroyCounter.initial");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String initial = bufferedReader.readLine();
counter = Integer.parseInt(initial);
return;
}
catch(FileNotFoundException ignored) { } catch(IOException ignored) { }
catch(NumberFormatException ignored) { } counter = 1;
}
public void destroy() { saveState();
}
Questo metodo è eseguito quando la servlet è creata (una volta sola alla prima richiesta)
Questo metodo è eseguito automaticamente
prima dello shutdown del Web Server
24
Comunicazione distribuita
Invocazione di metodi sull’oggetto remoto
Java VM1
Port1
Java VM2
Port 2
Socket, Servlet e Remote Method Invocation 25
RMI: goal
• Rendere trasparente l’invocazione remota di metodi su oggetti Java che risiedono su diverse Virtual machines (evoluzione di Remote Procedure Call, RPC)
• offrire un modello distribuito che preservi maggiormente la semantica degli oggetti Java
• rendere il piu’ semplice possibile la scrittura di applicazioni distribuite
Livello di Trasporto Rete Livello di Trasporto Livello di riferimento
remoto
Livello di riferimento remoto Livello stub Livello stub
Applicazione Server
Architettura RMI
Applicazione Client Supporta vari
protocolli di invocazione:
unicast, multicast
Si occupa della effettiva connessione,
Ogni livello è indipen- dente dall’altro!
Si occupa di preparare (marshalling) la remote call e gli oggetti per la trasmissione
Socket, Servlet e Remote Method Invocation 27
Architettura RMI
• Il sistema RMI e` costituito da tre livelli per supportare flessibilità nella comunicazione
• Ogni livello ha le sue interfacce di comunicazione con relativi protocolli
– stub (e skeleton) layer: canale di comunicazione tra clients e server
– remote reference layer: supporto di diversi protocolli di invocazione tipo Unicast e Multicast – transport layer: supporta la comunicazione a
basso livello, tipo TCP/IP
28
RMI
Simile all’invocazione di metodi locali
• i parametri dei metodi possono essere oggetti
• il polimorfismo e` supportato: oggetti diversi possono rispondere a stessi messaggi
ma
• i client interagiscono con interfacce di oggetti (stub) non con la loro implementazione (che sta nella VM remota)
• parametri passati per copia, non per referenza
(passaggio per referenza solo dentro a una VM)
Socket, Servlet e Remote Method Invocation 29
RMI in pratica
• L’oggetto blu sulla JVM Client desidera inviare un messaggio all’oggetto rosso sulla JVM Server, gli oggetti giallo e azzurro fanno parte dei parametri del messaggio
• L’oggetto rosso sulla JVM Server terminata l’esecuzione restituisce l’oggetto verde come valore di ritorno oppure solleva un’eccezione
IP Address IP Address
Server Client
JVM JVM
messaggio valore di ritorno o eccezione
RMI in pratica: Interfaccia
• Il client deve disporre di un’interfaccia che descriva l’oggetto remoto
• È necessario che l’interfaccia estenda java.rmi.Remote
• Ogni metodo descritto puo` lanciare un’eccezione di tipo java.rmi.RemoteException
public interface Distributor extends java.rmi.Remote { Job getNewJob() throws java.rmi.RemoteException;
Job getNewJob(Message msg) throws java.rmi.RemoteException;
}
Socket, Servlet e Remote Method Invocation 31
RMI in pratica:
Implementazione
• Il Server implementa la classe che esegue praticamente i metodi che sono descritti nell’interfaccia remota
• Questa classe è necessario che estenda la classe
java.rmi.server.UnicastRemoteObject (attualemente l’unica disponibile, multicast in una futura versione) che rende accessibile le sue istanze remotamente (puo` creare uno stub per la classe)
public class DistributorImpl
extends java.rmi.server.UnicastRemoteObject implements Distributor {
[..]
public Job getNewJob() throws java.rmi.RemoteException { […]
} […]
}
32
RMI in pratica: rmiregistry, bind (rebind)
• Gli oggetti remoti sono individuati tramite un IP, un numero di porta e un nome (una stringa)
• server registry: processo “pagine gialle”
IP Address IP Address
Server Client
JVM JVM
registry
<IP, port, name>
<IP, port, name>
stub Naming.rebind
Non è necessario registrare l’oggetto verde
Lo stub è necessario durante il bind Si registra
l’oggetto rosso presso il servizio di pagine gialle
Reference Layer:
apertura di un server socket
Socket, Servlet e Remote Method Invocation 33
RMI in pratica: rmiregistry, bind (rebind)
• La classe Naming appartiene al package java.rmi
• rmiregistry puo` anche essere attivato indipendentemente dal server tramite il comando “rmiregistry 2000”
public DistributorImpl() throws RemoteException { […]
try {
java.rmi.registry.LocateRegistry.createRegistry(2000);
Naming.rebind("rmi://130.192.239.145:2000/distributor",this);
}
catch (Exception e) {
System.err.println("Failed to bind to RMI Registry");
System.exit(1);
} }
porta
IP address nome oggetto
remoto
RMI in pratica: rmiregistry, lookup
IP Address IP Address
Server Client
JVM JVM
registry
<IP, port, name>
<IP, port, name>
stub stub
Naming.lookup
• Il client ottiene uno stub (surrogato dell’oggetto rosso presso il client) tramite il server registry
• Deve conoscerne IP, porta e nome
Socket, Servlet e Remote Method Invocation 35
RMI in pratica: rmiregistry, lookup
• L’oggetto remoto è contattato tramite il server registry
• È necessario conoscerne l’indirizzo IP, il numero della porta e il nome con cui è registrato
public class Client { Distributor server;
[…]
public Client() { try {
server = (Distributor)Naming.lookup(
"rmi://130.192.239.145:2000/distributor”);
}
catch(Exception e) {
System.out.println("Failed to find distributor" + e.getMessage());
} }
Tipo definito dall’interfaccia!
36
RMI in pratica: stub client
IP Address IP Address
Server Client
JVM JVM
registry
<IP, port, name>
stub stub messaggio
• L’oggetto blu invia un messaggio al surrogato oggetto rosso presso lo stub client
• Lo stub client inizializza la chiamata remota ed organizza i parametri da inviare
L’oggetto giallo e azzurro vengono
serializzati e organizzati per la spedizione (marshalling)
Garbage collector:
mantiene un riferimento all’oggetto rosso: non puo` essere eliminato
Socket, Servlet e Remote Method Invocation 37
RMI in pratica: invio messaggio
• L’oggetto remoto è ora utilizzabile come un qualsiasi oggetto locale
• lo stub ne è un surrogato public class Client {
[..]
public void process() { try {
Job myJob = server.getNewJob(new Message("Richiesta Job!"));
myJob.process();
}
catch (Exception e) {
System.out.println("Failed to receive job " + e.getMessage());
} } [..]
}
RMI in pratica: connessione
IP Address IP Address
Server Client
JVM JVM
stub stub
• Il livello di trasporto è responsabile per una connessione, nel server ascolta le richieste in arrivo
• mantiene la tabella degli oggetti remoti nel particolare address space
• Scambia le informazioni con il reference layer
registry
<IP, port, name>
Il livello di trasporto apre un socket per la connessione
Socket, Servlet e Remote Method Invocation 39
RMI in pratica: stub server
IP Address IP Address
Server Client
JVM JVM
stub stub
TCP/IP
registry
<IP, port, name>
• Lo stub server riorganizza i parametri (unmarshalling)
• individua l’oggetto da chiamare attivando il metodo desiderato
(informazione contenuta nel pacchetto ricevuto)
Attenzione nonvi è nessun riferimento agli oggetti giallo e azzurro sul client passati
come parametro:
sono copie!
40
RMI in pratica: la risposta
IP Address IP Address
Server Client
JVM JVM
stub stub
Invia valore di ritorno o eccezione
TCP/IP
• Lo stub del server cattura e riorganizza il valore restituito dall’evecuzione del metodo sull’oggetto rosso
• Lo stub server invia allo stub del client un pacchetto contenente le
informazioni raccolte (l’oggetto verde)
registry
<IP, port, name>
Socket, Servlet e Remote Method Invocation 41
RMI in pratica: la risposta
• Il server esegue il metodo invocato ed invia il valore di ritorno come se la chiamata fosse locale
public DistributorImpl() throws RemoteException { […]
public Job getNewJob(Message msg) { System.out.println(msg);
if( count < jobs.size()) {
return (Job)jobs.elementAt(count++);
} else {
System.exit(0);
}
return null;
} […]
}
RMI in pratica: ricezione
IP Address IP Address
Server Client
JVM JVM
stub stub
registry
<IP, port, name>
• Lo stub client rioganizza le
informazioni ricevute o l’eccezione sollevata
• La connessione viene quindi disattivata
Socket, Servlet e Remote Method Invocation 43
RMI in pratica: ricezione
• Il valore di ritorno è utilizzato come se fosse ora un oggetto locale ma non ha nessun riferimento con quello creato sul server (come per I parametri inviati con la chiamata)
public class Client { [..]
public void process() { try {
Job myJob = server.getNewJob(new Message("Richiesta Job!"));
myJob.process();
}
catch (Exception e) {
System.out.println("Failed to receive job " + e.getMessage());
} } [..]
}
44
RMI: riassunto
• Nell’esempio che vedremo:
– javac *.java
– rmic -v1.2 DistributorImpl – rmiregistry 2000 &
– java DistributorImpl – java Client
Senza l’opzione viene creato anche il file
DistributorImpl_Skel.class compatibile sia con
Java 1.1 e 1.2 Crea il file:
DistributorImpl_Stub.class
Attiva il server registry
Attiva il server Esegue il client Dopo in bind è attivo
un thread separato per gestire le richieste di
connessione, termina con CTRL-C
Socket, Servlet e Remote Method Invocation 45
RMI: download dello stub
IP Address IP Address
Server Client
JVM JVM
registry
<IP, port, name>
<IP, port, name>
stub stub
TCP/IP
Web Server
HTTPdownload
Security Manager file di criteri
• Lo stub generato dal server deve essere disponibile al client ma questo, in genere, è
remoto…
• Puo` essere scaricato tramite HTTP
RMI: security manager
• RMISecurityManager con l’associato file di criteri permette di scaricare mediante il protocollo HTTP
• È necessario un file di criteri public class Client {
Distributor server;
[…]
public Client() { try {
System.setSecurityManager(new RMISecurityManager());
server = (Distributor)Naming.lookup(
"rmi://130.192.239.145:2000/distributor”);
}
catch(Exception e) {
System.out.println("Failed to find distributor" +
Socket, Servlet e Remote Method Invocation 47
RMI: security manager
• Per utilizzare il file di criteri nel client:
– java -Djava.security.policy=client.policy
• Per indicare da dove scaricare il file stub dal server:
– java -
Djava.rmi.server.codebase=http://nbbaldoni.di.unito.it/~b aldoni/dowload/rmi1/ DistributorImpl
grant {
permission java.net.SocketPermission "130.192.239.145:1024-65535", "connect";
permission java.net.SocketPermission "130.192.239.1:80", "connect";
};
file client.policy
48
RMI: polimorfismo
IP Address IP Address
Server Client
JVM JVM
registry
<IP, port, name>
<IP, port, name>
stub stub
TCP/IP
Web Server
HTTPdownload
Security Manager file di criteri
• L’oggetto inviati tramite RMI preservano il loro vero tipo
• Ma se il valore restituito è piu`
specializzato di quello atteso dal client che succede?
• Download delle classi per trattare l’oggetto specializzato!
Socket, Servlet e Remote Method Invocation 49
RMI: polimorfismo
• E se l’oggetto inviato è piu` specializzato di quello atteso dal server?
• Download delle classi via HTTP durante l’esecuzione del metodo sull’oggetto remoto (sul server)
• IL server necessita a sua volta di un Security Manager per il controllo delle classi scaricate
• È nececessario un file di criteri per il download anche per il server
• Il client deve specificare dove scaricare le classi
RMI: polimorfismo
IP Address IP Address
Server Client
JVM JVM
registry
<IP, port, name>
<IP, port, name>
stub stub Web Server
Web Server HTTP
download HTTPdownload
Security Manager file di criteri file di criteri