510 likes | 655 Vues
Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi. Gianpaolo Cugola http://www.elet.polimi.it/~cugola cugola@elet.polimi.it. Sommario. Il concetto di applicazione distribuita L’architettura di una applicazione distribuita Il paradigma a scambio di messaggi
E N D
Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi Gianpaolo Cugola http://www.elet.polimi.it/~cugola cugola@elet.polimi.it
Sommario • Il concetto di applicazione distribuita • L’architettura di una applicazione distribuita • Il paradigma a scambio di messaggi • Il paradigma client-server • Il paradigma peer-to-peer • Internet e Intranet • Il protocollo TCP/IP • Lo sviluppo di applicazioni distribuite in Java • I socket TCP/IP in Java • L’invocazione remota di metodi in Java (RMI) Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Applicazione distribuita • Definizione: • Applicazione costituita da due o più processi che eseguono in parallelo su macchine distinte connesse da una rete di comunicazione • I processi che costituiscono una applicazione distribuita cooperano sfruttando i servizi forniti dalla rete di comunicazione Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Applicazione distribuita: un esempio Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Internet e le applicazioni distribuite • Gli anni 90 hanno visto il boom delle tecnologie di telecomunicazione • Il caso di Internet: milioni di computer collegati in una rete unica • Effetto pratico: • Un aumento esponenziale nella richiesta di applicazioni distribuite • Principali campi di impiego delle applicazioni distribuite • Comunicazione: e-mail, web, chat, news • Supporto al lavoro collaborativo: sistemi di workgroup e workflow • Supporto alle attività commerciali: sistemi di commercio elettronico, sistemi di home banking Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Architettura di una applicazione distribuita • Una applicazione distribuita è caratterizzata dalla propria architettura run-time • Definizione: • Con il termine “architettura run-time” si indica l’organizzazione dei componenti (processi) che costituiscono l’applicazione a run-time • Elementi caratteristici di una architettura • Tipologia e ruolo dei componenti • Tipologia delle connessioni Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Le architetture basate su scambio messaggi • Lo scambio messaggi è il paradigma di comunicazione più semplice per lo sviluppo di applicazioni distribuite • Identifica una categoria di architetture distinte • Caratteristiche: • Ogni componente dell’applicazione possiede uno o più indirizzi • Un componente A comunica con un componente B spedendo un messaggio ad uno degli indirizzi associati a B • Principali architetture basate su scambio messaggi: • Architetture client-server • Architetture peer-to-peer • Architetture a tre livelli (three-tiered architecture) Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Richiestadocumento Inviodocumento L’architettura client-server • Caratteristiche: • Componenti distinti in due tipi: client e server • I server erogano un servizio • I client sfruttano tale servizio • Comunicazioni basate su scambio messaggi • Esempio: il web • Client: il browser • Server: il demone http che fornisce i documenti ai client Browser Demone http Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
L’architettura peer-to-peer • Caratteristiche • Componenti indifferenziati: agiscono tanto da richiedenti di un servizio quanto da fornitori di servizio • Comunicazioni basate su scambio messaggi • Esempio: talk Blah blah blah Blah blah blah Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
L’architettura a tre livelli • Caratteristiche: • Tre tipologie di componenti: • Client • Server applicativo • Data base • Comunicazioni basate su scambio messaggi • Esempio: applicazioni di commercio elettronico DB Client(browser + ActiveX o Applet) Server applicativo (demone http+cgi o servlet) Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Internet e Intranetuna breve panoramica delle caratteristiche e dei protocolli di comunicazione Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Internet: architettura logica Serverweb Client web Serverftp Client web Rete Serverweb Client ftp Client web Serverftp Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Internet: architettura fisica Host Gateway Internetprovider Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
ISO/OSI Internet Protocol Suite Application Telnet NFS FTP Presentation Web-NFS SMTP Session HTTP RPC Transport TCP e UDP Network IP e Protocolli di routing Data Link Non specificati Physical Internet Protocol Suite Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Il protocollo IP • Caratteristiche: • protocollo connectionless • si occupa dell’instradamento e della rilevazione d’errore • Indirizzo IP: • indirizzo numerico (32 bit) univocamente associato ad una interfaccia di rete di un host • Esempio: 131.175.21.8 • I gateway hanno due o piu’ indirizzi IP diversi ed una tabella di instradamento Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Gli indirizzi simbolici ed i DNS • Un indirizzo simbolico può sostituire un indirizzo IP • Un indirizzo simbolico è composto da un nome di dominio e da un nome di host • esempio: ipmel2.elet.polimi.it • Il file hosts: • esempio: 127.0.0.1 localhost 131.175.21.8 www.polimi.it 131.175.21.1 ipmel2 ipmel2.elet.polimi.it • I Domain Name Servers (DNS): • costituiscono un data base distribuito per i nomi simbolici • permettono l’associazione nome simbolico/indirizzo IP Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Il protocollo TCP • Caratteristiche: • protocollo connection-oriented (indirizzo IP + porta TCP) • fornisce un servizio full-duplex, con acknowledge e correzione d’errore • Due host connessi su Internet possono scambiarsi messaggi attraverso canali TCP • TCP costituisce l’infrastruttura di comunicazione della maggior parte dei sistemi basati su scambio messaggi su Internet Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Il protocollo UDP • Caratteristiche: • protocollo connectionless (indirizzo IP + porta UDP) • fornisce un servizio di correzione d’errore • Non assicura la consegna nè, tantomeno, l’ordine di invio (unreliable, best-effort protocol) • Utilizzato nelle applicazioni client-server di tipo richiesta/risposta • Esempi: NFS, DNS Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Intranet • Il boom di Internet ha favorito la diffusione del protocollo TCP/IP anche in ambito locale • Intranet: rete locale basata sui protocolli di Internet (TCP/IP) Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Lo sviluppo di applicazionidistribuite basate su scambio messaggi in Java Socket TCP e UDP, RMI Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Socket TCP e UDP • Con il termine “socket” si indica un’astrazione del sistema operativo per modellare la comunicazione tramite TCP o UDP • Nati in ambiente Unix BSD (1982) • Disponibili su tutte le piattaforme • Le librerie per la gestione dei socket sono fornite con tutti i principali linguaggi di programmazione Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
P3 Socket TCP: meccanismo di funzionamento Server Client P1 P2 Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Socket UDP: meccanismo di funzionamento Server Client P1 P2 Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Socket TCP e UDP in Java • Le classi per la gestione dei socket (TCP o UDP) sono parte del package java.net • Classi principali • Classi di uso generale • InetAddress • Socket TCP • ServerSocket • Socket • Socket UDP • DatagramSocket • MulticastSocket • DatagramPacket Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
La classe InetAddress • Descrive un indirizzo IP • Non ha costruttori pubblici • Metodi principali • public static InetAddress getByName(String host) • public static InetAddress getLocalHost() • public String getHostAddress() • public String getHostName() • public boolean isMulticastAddress() Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
La classe ServerSocket • Usata dal lato server • Costruttore principale: • public ServerSocket(int port) • Metodi principali: • public synchronized void setSoTimeout(int timeout) • permette di scegliere un timeout per la accept (in millisecondi) • public synchronized int getSoTimeout() • public Socket accept() • bloccante se timeout=0 • public InetAddress getInetAddress() • public int getLocalPort() • public void close() Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
La classe Socket • Costruttori principali: • public Socket(String host, int port) • public Socket(InetAddress host, int port) • Metodi principali: • public InetAddress getInetAddress() • public InetAddress getLocalAddress() • public int getPort() • public int getLocalPort() • public InputStream getInputStream() • public OutputStream getOutputStream() • public void close() • public synchronized void setSoTimeout(int timeout) • permette di scegliere un timeout per la lettura dei byte dall’InputStream associato (in millisecondi) • public synchronized int getSoTimeout() Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
La classe DatagramSocket • Usata per inviare e ricevere messaggi UDP • Costruttori principali • public DatagramSocket() • public DatagramSocket(int port) • Metodi principali • public void close() • public void connect(InetAddress address, int port) • public void disconnect() • public void setSoTimeout(int timeout) • public int getSoTimeout() • public void receive(DatagramPacket p) • public void send(DatagramPacket p) Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
La classe MulticastSocket • Usata per inviare e ricevere messaggi multicast • Sottoclasse della classe DatagramSocket • Costruttori principali • public MulticastSocket() • public MulticastSocket(int port) • Metodi principali • public void joinGroup(InetAddress mcastaddr) • public void leaveGroup(InetAddress mcastaddr) • public void send(DatagramPacket p, byte ttl) • public void setTimeToLive(int ttl) • public byte getTimeToLive() Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
La classe DatagramPacket • Rappresenta un messaggio UDP • Costruttore principale • public DatagramPacket(byte[] buf, int length) • Metodi principali • public InetAddress getAddress() • public int getPort() • public byte[] getData() • public void setData(byte[] buf) • public int getLength() • public void setLength(int length) Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Applicazioni client-server basate su socket TCP: schema di funzionamento • L’applicazione “server” rimane in attesa su una porta logica • L’applicazione “client” apre una connessione verso la macchina sulla quale gira il server specificando la porta • Il server riceve la connessione e apre una canale di comunicazione • Caso 1: • Il server riceve il messaggio inviato dal client, lo interpreta e svolge il servizio richiesto inviando l’eventuale risposta • Al termine si rimette in attesa di nuove connessioni • Caso 2: • Il server crea un nuovo thread incaricato di gestire la connessione e si rimette in attesa di nuove connessioni Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
import java.net.*; import java.io.*; public class ServerTCP { public static void main(String[] args) { ServerSocket sSock = null; try {sSock = new ServerSocket(4444); } catch (IOException e) { System.out.println("Could not listen on port: 4444, "+e);System.exit(-1); } Socket sock = null; while(true) { try { sock = sSock.accept(); new ServerThread(sock).start(); } catch (IOException e) { System.out.println("Accept failed, " + e); System.exit(1); } } } } class ServerThread extends Thread { Socket sock; public ServerThread(Socket sock) { this.sock=sock; } public void run() { String inputLine; try { BufferedReader br= new BufferedReader( new InputStreamReader( sock.getInputStream())); while((inputLine=br.readLine())!=null){ System.out.println(inputLine); if (inputLine.equals("Bye.")) break; } br.close(); sock.close(); }catch (IOException e) {e.printStackTrace();} } } I socket TCP: un esempio - 1 Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
I socket TCP: un esempio - 2 import java.io.*; import java.net.*; public class ClientTCP { public static void main(String[] args) { Socket sock=null; OutputStreamWriter osw=null; try{ sock=new Socket(args[0],4444); osw=new OutputStreamWriter(sock.getOutputStream()); } catch(IOException e) { System.out.println("Error opening socket, "+e); System.exit(-1); } try{ osw.write(args[1]); osw.write("Bye."); osw.close(); sock.close(); } catch(IOException e) { System.out.println("Error sending message, "+e); System.exit(-1); } } } Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
I socket UDP: un esempio - 1 import java.net.*; public class ServerUDP { public static void main(String[] args) { DatagramSocket sock = null; String mess=null; DatagramPacket pack = new DatagramPacket(new byte[128],128); try { sock = new DatagramSocket(4444); } catch (SocketException e) { System.out.println("Error opening socket, "+e); System.exit(-1); } while(true) { try { sock.receive(pack); } catch (java.io.IOException e) { System.out.println("Error receiving packet, " + e); System.exit(-1); } mess=new String(pack.getData()); System.out.println(mess); if (mess.equals("Bye.")) break; } sock.close(); } } Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
I socket UDP: un esempio - 2 import java.net.*; public class ClientUDP { public static void main(String[] args) { DatagramSocket sock = null; DatagramPacket pack = null; try{ sock=new DatagramSocket(); sock.connect(InetAddress.getByName(args[0]), 4444); } catch(java.io.IOException e) { System.out.println("Error opening socket, "+e); System.exit(-1); } try{ byte[] buf=args[1].getBytes(); pack=new DatagramPacket(buf,buf.length); sock.send(pack); } catch(java.io.IOException e) { System.out.println("Error sending message, "+e); System.exit(-1); } sock.disconnect(); sock.close(); } } Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Le altre classi del package java.net • Il package java.net fornisce altre classi per: • usare gli URL • sfruttare il protocollo HTTP • Autenticare un utente Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Dai socket alla Remote Method Invocation • I socket TCPe UDP forniscono un valido strumento per la programmazione di applicazioni distribuite... • ... ma risultano talvolta di difficile utilizzo • Occorre definire un “protocollo” per l’invio delle richieste di servizio e delle risposte... • ... con relativa codifica e decodifica dei parametri in sequenze di byte • La Remote Method Invocation (RMI) permette di superare tali limiti Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Remote Method Invocation • Attraverso i servizi RMI è possibile invocare metodi su un oggetto remoto come se si trattasse di un oggetto locale • Un oggetto remoto è ogni oggetto che implementi una interfaccia che estende l’interfaccia java.rmi.Remote • Gli oggetti remoti si comportano come gli oggetti tradizionali • è possibile passare riferimenti ad oggetti remoti nelle chiamate a metodo • La differenza principale riguarda il passaggio di parametri non remoti a metodi di oggetti remoti • il passaggio è fatto per copia (i parametri devono essere serializzabili) • Lo stesso vale per i valori di ritorno restituiti da metodi di oggetti remoti Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
lookup bind invoke Server_Skel Server_Stub IntServer IntServer RMI: schema di funzionamento host A host B rmiregistry Client Server Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Implementazione di una applicazione client/server basata su RMI: server - 1 • Si crea una interfaccia che descriva i servizi forniti dal server • l’interfaccia deve estenderejava.rmi.Remote • tutti i metodi devono dichiarare di sollevare l’eccezione java.rmi.RemoteException Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Implementazione di una applicazione client/server basata su RMI: server - 2 • Si implementa il server • come sottoclasse di java.rmi.server.UnicastRemoteObject • oppure come classe “generica” che reimplementi i metodi equals, hashCode e toString in maniera da mantenere la semantica corretta in ambito distribuito • in tal caso il server deve essere esplicitamente esportato per essere visibile ai client, invocando il metodo:java.rmi.server.UnicastRemoteObject.exportObject • il server può essere registrato sul rmiregistry attraverso un nome simbolico nella forma “//host:porta/nome” • il server dovrebbe impostare come security manager un RMISecurityManager Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Implementazione di una applicazione client/server basata su RMI: server - 3 • Si compila il server • Si creano le classi stub e skeleton attraverso il compilatore rmic • Si lancia l’applicazione rmiregistry • Si lancia il server Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Implementazione di una applicazione client/server basata su RMI: client • Si implementa il client • Il client ottiene un riferimento all’oggetto remoto • passato da altri oggetti • ottenuto accedendo allo rmiregistry • Il client può invocare tutti i metodi elencati nell’interfaccia remota implementata dal server • Per il client non occorre alcun processo di compilazione speciale Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Implementazione di una applicazione client/server basata su RMI: rmiregistry • Il rmiregistry fornisce un servizio di directory per RMI • Un server RMI si può registrare su un rmiregistry attraverso un nome simbolico • Un client RMI può: • ottenere un riferimento ad un server RMI indicando il nome simbolico • chiedere la lista dei server disponibili • Tali servizi sono realizzati attraverso le classi: • java.rmi.Naming • java.rmi.registry.LocateRegistry • java.rmi.registry.Registry • e attraverso l’eseguibile rmiregistry Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Esempio RMI: l’interfaccia del server import java.rmi.*; public interface RMIServer extends Remote { public void print(String s) throws RemoteException; } Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Esempio RMI: l’implementazione del server import java.rmi.*; import java.rmi.server.UnicastRemoteObject; public class RMIServerImpl extends UnicastRemoteObject implements RMIServer { public static void main(String[] args) { try { System.setSecurityManager(new RMISecurityManager()); RMIServerImpl server = new RMIServerImpl(); Naming.rebind("polimi/RMIServer", server); System.out.println("Server bound"); } catch (Exception e) { e.printStackTrace(); } } public RMIServerImpl() throws RemoteException {} public void print(String s) throws RemoteException { System.out.println(s); } } Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Esempio RMI: il client import java.rmi.*; public class RMIClient { public static void main(String[] args) { try { System.out.println("Looking up server..."); RMIServer server = (RMIServer) Naming.lookup("rmi://"+args[0]+"/polimi/RMIServer"); System.out.println("Server bound..."); server.print("prima prova"); server.print("seconda prova"); } catch (Exception e) { e.printStackTrace(); } } } Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Esempio RMI: la compilazione • javac RMIServerImpl.java • compila il server • javac RMIClient.java • compila il client • rmic RMIServerImpl • crea le classi RMIServer_Skel e RMIServer_Stub • rmiregistry • lancia il registry • java RMIServerImpl • lancia il server • java RMIClient localhost • lancia il client dicendo di collegarsi a localhost Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Il deployment • Le classi stub devono essere accessibili al client (attraverso un opportuno class loader) • Il caso delle applet • le classi stub devono essere inserite nella stessa directory della classe dell’applet (sul server http) • il classloader usato è AppletClassLoader • il server RMI deve girare sullo stesso host su cui gira il server http dal quale viene scaricata l’applet Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi
Domande? Lo sviluppo di applicazioni distribuite secondo il paradigma a scambio di messaggi