Sistemi informativi applicati (reti di calcolatori): appunti delle lezioni Architetture client/server: applicazioni client 1 Architetture client/server: un esempio World wide web è un esempio particolarmente semplice di un sistema basato su un architettura C/S Browser 1. richiesta: http://server/prova.html 3. risposta: il file prova.html Server web 2. elaborazione: recupera il file Il browser, nel ruolo di client, deve inviare la richiesta in modo tale che: giunga al server web sia correttamente interpretabile dal server web Il server web, nel ruolo di server, deve inviare la risposta in modo tale che: giunga al browser sia correttamente interpretabile dal browser Dunque: il browser e il server web devono essere connessi mediante un infrastruttura di trasmissione il browser e il server web devono parlare la stessa lingua 2
Requisiti e soluzioni Client e server devono essere connessi mediante un infrastruttura di trasmissione: è il compito dell'infrastruttura fisica e, sopra di essa, di TCP/IP, che mette a disposizione un sistema affidabile di trasporto e di indirizzamento Client e server devono parlare la stessa lingua, un protocollo che si pone sopra a TCP/IP e definisce gli aspetti applicativi della comunicazione (dato che tutti i problemi di trasmissione si suppone siano gestiti appunto da TCP/IP) Le varie applicazioni client e server non sanno nulla di trasmissione, e si occupano solo delle questioni relative al protocollo applicativo che parlano (HTTP per web, SMTP, POP3 e/o IMAP4 per email, ) Questa è una caratteristica generale: tutte le applicazioni basate su Internet affidano la risoluzione dei problemi di trasmissione a TCP/IP TCP/IP, e TCP in particolare, mette a disposizione dei programmatori un insieme di comandi che consentono alle applicazioni stesse di risolvere tutti i problemi di trasmissione senza occuparsi dei relativi dettagli: questa interfaccia di programmazione è fondata sulla metafora delle porte (port) e dei connettori (socket) 3 La logica C/S dal lato del client Ogni applicazione server è attiva su un calcolatore identificato da un indirizzo IP ed è in ascolto, in attesa di richieste, su una porta TCP Per connettersi a un applicazione server, dunque, un applicazione client deve aprire un socket specificando l indirizzo di un server (come indirizzo IP o, se un DNS è disponibile, come indirizzo simbolico) e una porta TCP La libreria LIUC (cioè il file liuc.jar) contiene in particolare il package it.liuc.net che contiene in particolare la classe ClientSocketManager il cui costruttore è: ClientSocketManager(java.lang.String host, java.lang.string port) La costruzione di un oggetto della classe ClientSocketManager corrisponde all apertura di un socket verso l applicazione in ascolto sulla porta port del calcolatore host I metodi della classe sono: void inviarichiesta(java.lang.string msg) Invia una richiesta al server connesso attraverso il socket java.lang.string ricevirisposta() Riceve la risposta prodotta dal server connesso attraverso il socket void chiudi() Chiude il socket 4
Applicazioni server e protocolli applicativi Naturalmente non siamo noi i primi a creare sistemi su TCP: esiste un elenco di applicazioni a ognuna delle quali è associata una well-known port (queste porte, tra 0 e 1023, sono assegnate e gestite dalla IANA, Internet Assigned Numbers Authority; si veda la pagina http://www.iana.org/assignments/port-numbers) e ognuna delle quali implementa un determinato protocollo applicativo per la comunicazione con i client Le porte sopra al 1023 sono generalmente utilizzabili per applicazioni custom Dal punto di vista dei client, identifichiamo tre categorie di protocolli (e quindi, corrispondentemente, di server); dal più semplice al più complesso: a risposta in connessione a risposta in ricezione di richiesta con stato 5 Protocolli a risposta in connessione Dal punto di vista del client la logica di questi protocolli è semplicissima: il client apre un socket se l operazione ha successo: o il client riceve la risposta dal server e quindi chiude il socket Protocolli di questo tipo sono, per esempio, daytime (porta 13) e qotd (quote of the day, porta 17) Ecco il più semplice client che parla questi protocolli: import it.liuc.net.*; public class ClientTCP0 { public static void main(string[] args) { System.out.println(new ClientSocketManager("host", "port").ricevirisposta()); dunque molto semplice anche perché, in effetti, dal punto di vista del client si tratta di un unico protocollo: le uniche differenze tra singoli protocolli riguardano il contenuto della risposta Naturalmente possiamo strutturare un po meglio (e più chiaramente) l applicazione 6
Protocolli a risposta in connessione /2 import it.liuc.io.*; import it.liuc.net.*; public class ClientTCP1 { public static void main(string[] args) { OutputManager myout = new OutputManager(); try { ClientSocketManager mysock = new ClientSocketManager("host", "port"); myout.scrivilinea(mysock.ricevirisposta()); mysock.chiudi(); catch (Exception e) { myout.scrivilinea("errore: " + e.getmessage()); System.exit(-1); ma la logica è evidentemente la stessa, e rimane semplice 7 Protocolli a risposta in ricezione di richiesta Dal punto di vista del client questi protocolli estendono la logica dei protocolli a risposta in connessione: il client apre un socket se l operazione ha successo: o il client invia una richiesta al server e si mette in attesa o il client riceve la risposta dal server e quindi chiude il socket Questi protocolli si caratterizzano per: il formato della richiesta che deve essere sottoposta al server il formato della risposta che il server invia al client Il più semplice esempio di un protocollo di questo tipo è echo (porta 7), che visualizza come risposta lo stesso testo inviato come richiesta 8
L esempio di un client echo import it.liuc.io.*; import it.liuc.net.*; public class ClientEcho { public static void main(string[] args) { OutputManager myout = new OutputManager(); try { InputManager myin = new InputManager(); while(true) { ClientSocketManager mysock = new ClientSocketManager("host", "7"); mysock.inviarichiesta(myin.leggilinea("> ")); myout.scrivilinea(mysock.ricevirisposta()); mysock.chiudi(); catch (Exception e) { myout.scrivilinea(e.getmessage()); System.exit(-1); 9 http HyperText Transfer Protocol (porta 80) è un protocollo a risposta in ricezione di richiesta; le sue specifiche di base sono molto semplici: sia la richiesta sia la risposta hanno lo stesso formato generale: una linea iniziale zero o più linee di intestazione (header) una linea bianca zero o più linee di contenuto (body) del messaggio Un esempio di dialogo http è: richiesta: GET /dir/file.html HTTP/1.0 Accept: */* User-Agent: nome del client Host: host:porta linea bianca risposta: HTTP/1.0 200 OK Date: data attuale Content-Type: text/html Server: nome del server Content-Length: lunghezza del file linea bianca <html> <body> prosegue con il resto del file 10
Protocolli con stato Dal punto di vista del client questi protocolli estendono la logica dei protocolli a risposta in ricezione di richiesta: il client apre un socket se l operazione ha successo: o il client invia una prima richiesta al server e si mette in attesa o il client riceve la risposta dal server o il client invia una seconda richiesta al server e si mette in attesa o il client riceve la risposta dal server o o alla fine, il client chiude il socket Questi protocolli si caratterizzano per: il formato della serie di richieste che devono essere sottoposte al server il formato della serie di risposte che il server invia al client 11