Sistemi informativi applicati (reti di calcolatori): appunti delle lezioni Architetture /: applicazioni 1 La logica dei Abbiamo visto che un applicazione si connette e comunica con un applicazione mediante un, dotato di funzioni sia per l invio di richieste sia per la ricezione di risposte: 1. richiesta 2. risposta verso il Il viene attivato all esecuzione dell applicazione La logica della gestione dei al lato è più complessa Ogni applicazione deve stare in ascolto su una porta TCP nell attesa di richieste ogni volta che gli giunge una richiesta deve attivare il dialogo e nello stesso tempo dovrebbe rimettersi in ascolto, per gestire la ricezione di successive richieste Come strutturare l applicazione in modo da soddisfare questi requisiti? 2
La logica dei dal lato del Ogni applicazione : apre e tiene aperto un listener su una porta TCP, con cui si mantiene in ascolto delle richieste di connessione che gli giungono dalla rete per ogni richiesta di connessione che giunge, apre un handler e trasferisce il controllo dal listener al nuovo, delegato della gestione del dialogo con il che ha inviato la richiesta mediante il handler riceve le richieste dal e gli invia le risposte 1. richiesta di connessione 3. dialogo applicativo: scambio richieste - risposte listener handler 2. trasferimento del controllo La richiesta 1 è un operazione standardizzata, effettuata specificando l indirizzo (IP o simbolico) del e la porta TCP di destinazione il comando 2 è un operazione interamente -side, che non richiede dunque il trasferimento di alcuna informazione di natura applicativa il dialogo 3 implementa il protocollo applicativo che condividono e 3 La struttura di un applicazione Nella sua versione più semplice, un applicazione può essere strutturata così: 1. crea un listener su una porta TCP e mettilo in attesa di richieste di connessione 2. crea un handler e connettilo al listener; all arrivo di una richiesta di connessione: 2.1. ricevi la richiesta applicativa 2.2. produci la risposta 2.3. invia la risposta 2.4. chiudi il handler e torna al passo 2 4
Strumenti per l implementazione La libreria LIUC (cioè il file liuc.jar) contiene in particolare il package it.liuc.net che contiene in particolare: la classe ListenerSocketManager: di cui è necessario utilizzare il solo costruttore: ListenerSocketManager(java.lang.String port) il parametro port è il numero della porta TCP su cui mettere in ascolto il la classe HandlerSocketManager: il cui costruttore è: HandlerSocketManager(ListenerSocketManager ) I metodi della classe sono: java.lang.string ricevirichiesta() Riceve la richiesta inviata al void inviarisposta(java.lang.string msg) Invia una risposta al connesso attraverso il void chiudi() Chiude il 5 L esempio di un (semplice) echo // nei commenti sono riportati riferimenti ai passi descritti nella slide precedente public class SimpleServerEcho { public static void main(string[] args) { ListenerSocketManager listenersock = new ListenerSocketManager("7"); //1 myout.scrivilinea("in esecuzione..."); while(true) { HandlerSocketManager handlersock = new HandlerSocketManager(listenersock); //2 String inputline = handlersock.ricevirichiesta(); //2.1 String outputline = inputline; //2.2 handlersock.inviarisposta(outputline); //2.3 handlersock.chiudi(); //2.4 catch(exception e) { System.exit(-1); 6
Server multiutente Il echo precedente ha un limite fondamentale: mentre è attivo il dialogo richiesta risposta tra il e un, il stesso risulta inaccessibile a richieste di connessione inviate da altri La soluzione di questo problema richiede un rilevante cambiamento nella struttura del, che deve essere implementato come una coppia di applicazioni: 1. richiesta di connessione 3. dialogo applicativo: scambio richieste - risposte listener handler A B il A è in ascolto delle richieste di connessione che gli giungono dalla rete; ogni volta che riceve una richiesta di connessione attiva un istanza del B il B, implementato come una classe distinta, è gestito come un sottoprocesso a esecuzione autonoma (thread) dell applicazione La realizzazione di una classe eseguibile come thread è un po tecnica 2. attivazione e trasferimento del controllo 7 L esempio di un (echo) parte A public class ServerEchoA { public static void main(string[] args) { ListenerSocketManager listenersock = new ListenerSocketManager("7"); myout.scrivilinea("in esecuzione..."); while(true) { new ServerEchoB(new HandlerSocketManager(listenersock)); catch(exception e) { System.exit(-1); Si tratta dunque di una versione ridotta del precedente: invece della gestione completa del handler, il loop istanzia la classe threaded passando come parametro una nuova istanza del handler 8
L esempio di un echo parte B public class ServerEchoB extends Thread { // classe dichiarata di tipo Thread HandlerSocketManager handlersock; public ServerEchoB(HandlerSocketManager handlersock) { this.handlersock = handlersock; start(); // attiva il thread, mettendo in esecuzione il metodo run() public void run() { String inputline = handlersock.ricevirichiesta(); String outputline = inputline; handlersock.inviarisposta(outputline); myout.scrivilinea(outputline); handlersock.chiudi(); catch(exception e) { 9 Da C/S a P2P (argomento avanzato) La logica / può essere impiegata anche per creare applicazioni in architettura peer-to-peer, in pratica introducendo nell applicazione sia un sia un app listener handler verso un altra app Nella sua versione più semplice, un applicazione di questo genere (per esempio un programma di chat) può essere strutturata così: crea un oggetto di una classe threaded entra nel loop del quando viene creato, l oggetto della classe attiva il thread, attivando un listener su una porta specificata e quindi entrando nel loop del 10