450 likes | 606 Views
UN SINGOLO COMPONENTE... ?. Finora ci siamo concentrati su un singolo programma = un singolo componente si leggono i dati di ingresso ... ... si elabora ( computazione ) ... ... si scrivono i risultati in uscita. Ma oggi quasi mai un’applicazione consi-ste in un singolo componente!
E N D
UN SINGOLO COMPONENTE... ? • Finora ci siamo concentrati su un singolo programma = un singolo componente • si leggono i dati di ingresso ... • ... si elabora (computazione) ... • ... si scrivono i risultati in uscita. • Ma oggi quasi mai un’applicazione consi-ste in un singolo componente! • un componente acquista molto più valore se può cooperare a creare progetti più grandi • elaborazione distribuita su rete
ARCHITETTURE MULTI-COMPONENTE • componenti software e hardware eterogenei • ogni componente forni-sce servizi agli altri com-ponenti e usa i servizi da essi forniti • necessità di protocolli di comunicazione • esecuzione distribuitanel tempo e nello spazio
ARCHITETTURA CLIENTE / SERVITORE Servitore: • un qualunque ente computazionale capace di nascondere la propria organizzazione interna • presentando ai clienti una precisa interfaccia per lo scambio di informazioni Cliente: • qualunque ente in grado di invocare uno o più servitori per svolgere il proprio compito
IL MODELLO INTERNET Cliente = browser Web • Internet Explorer, Netscape Navigator, ... Servitore = server Web (sul sito) Browser Web(cliente) Server Web rete Internet
IL PROTOCOLLO DI COMUNICAZIONE HTTP:HyperText Transfer Protocol 1) il cliente invia al server l’identificatore dellapagina richiesta (URL) http://www.unibo.it/studenti/stud.html 2) il server recupera il file corrispondente a quella pagina... ..../studenti/stud.html 3) ... e lo invia al cliente (byte per byte)
IL PROTOCOLLO DI COMUNICAZIONE Browser Web(cliente) http://..../studenti/stud.html 1 3 Server Web 2
IL PROTOCOLLO DI COMUNICAZIONE HTTP:HyperText Transfer Protocol Pregio: • è un protocollo molto semplice da gestire e da implementare Difetto: • nella versione base, è poco flessibile • il contenuto delle pagine web è prefissato • il server non fa alcuna elaborazione, si limita a prendere un file e spedirlo
HTTP: ESTENSIONI Obiettivo: • dare al server la possibilità di rispondere a una richiesta in modo “personalizzato” e flessibile(non solo fisso a priori) • esempio: fornire i risultati di una ricerca Come? • rendendo il server capace di eseguire un programma per rispondere alla richiesta. CGI:Common Gateway Interface
HTTP: ESTENSIONI Risultato: • qualunque programma può fornire i suoi servizi sul web • non più solo su un computer isolato! • non importa il linguaggio in cui è scritto • non importa come elabora (computazione) • importa che gestisca input e output nei mo-di previsti dagli standard, ossia che segua il MODELLO DI COORDINAZIONE previsto.
HTTP + CGI Con CGI, HTTP diviene aperto e flessibile: 1) il cliente invia al server l’URL della pagina richiesta, che però non è una vera pagina, ma il nome di un programma (xxxx): http://www.unibo.it/cgi-bin/xxxx 2) il server esegue il programma xxxx... ..../cgi-bin/xxxx 3) ... e invia il risultato al cliente.
HTTP + CGI Browser Web(cliente) http://..../cgi-bin/xxxx 1 Server Web 3 2 Programmaxxxx
HTTP + CGI Quindi: • è il programma che risponde al cliente,non più il server (fa solo da tramite) • tutto quello che il programma scrive sullostandard outputviene trasferito “pari pari” al cliente (il browser Web) • semplice testo, testo HTML, immagini, altro... • si può trasferire di tutto: basta che il cliente sappia come trattare quello che gli arriva.
CGI: UN MINI-ESEMPIO Un programma C che stampa “Hello World”... main(){ printf(“Hello World!”); } ...
CGI: UN MINI-ESEMPIO Fondamentale il “doppio a capo” ... portato “sulla rete”: main(){ printf(“Content-type: text/plain\n\n”); printf(“Hello World!”); } forma standard per avvertire il browser di “cosa gli sta arrivando” (in questo caso testo semplice, senza formattazioni particolari)
MINI-ESEMPIO: VARIANTE Un programma C che stampa “Hello World” come pagina HTML main(){ printf(“Content-type: text/html\n\n”); printf(“<H1>Here we are!</H1>”); printf(“<P><H2>Hello World!</H2>”); fflush(stdout); } Questa volta stiamo inviando testo HTML “doppio a capo” opportuno svuotare il buffer di output per garantire che tutto il testo sia effettivamente inviato
UNA PRECISAZIONE • Questi programmi devono essere compilati come normali programmi da console, non come programmi (pseudo-) grafici! • il server presuppone di poter parlare col programma tramite i normali canali di I/O, non tramite finestre di un qualche tipo! • Quindi, non si può usare il Turbo C! • Occorre DJgpp • o un qualunque compilatore C che produca eseguibili “da linea di comando” (DOS-like)
E PER FARE LE PROVE..? • Non è necessario avere accesso a un ser-ver web situato chissà dove • È possibile installarne uno localmente, sul proprio computer • ce ne sono a decine in rete, molti gratuiti... • ...ma non tutti supportano bene le CGI! • Sul sito del corso trovate Vq Server • un web server scritto in Java (richiede Java per funzionare), molto completo, e gratuito!
HTTP + CGI • Al momento, però, il programma non riceve dati di ingresso, quindi ha un output fisso! • Invece, vogliamo che il cliente (browser) possa inviare al programma opportuni dati di ingresso per guidarne l’elaborazione. Come fare? Due possibili modi: • con il sub-protocollo GET • con il sub-protocollo POST
INVIO DI DATI con GET • Il cliente invia i dati appendendoli all’URL • un punto interrogativo come separatore iniziale • seguito da qualunque cosa, ma senza spazi! http://www.unibo.it/cgi-bin/xxxx?dati • il server pone tutto ciò che segue il ? nella variabile di ambiente QUERY_STRING • il programma può recuperarla con la funzione di libreria getenv()[in stdlib]: char *s = getenv("QUERY_STRING")
ESEMPIO Un programma C che ristampa quello che ri- ceve (eco): main(){ char *st = getenv("QUERY_STRING"); printf(“Content-type: text/plain\n\n”); printf(“Buongiorno %s !”, st); fflush(stdout); } Ricordare il “doppio a capo” ristampa la stringa st che ha ricevuto
ESEMPIO Il browser può invocarlo ad esempio così: L’URL ha la forma:.../cgi-bin/....../cgi/.... ristampa la stringa che ha ricevuto
UNA RIFLESSIONE SULL’ESEMPIO • Certo, questo esempio è estremamente banale, perfino inutile... • ..ma dimostra che “portare un programma sul Web” è semplicissimo basta rispettare il modello di coordinazione previsto dallo standard (qui, CGI) • Anche un programma che da solo sarebbe stato di modesta utilità, portato sul Web può essere utile ad altri • diventa accessibile da tutto il mondo!
I MODULI (FORM) • In pratica, nessuno si sogna di scrivere i dati nell’URL “a mano” • Tipicamente, l’utente compila un modulo grafico e preme un bottoneper inviare i dati UN “FORM” scritto in HTML • Il risultato è che il cliente (browser): • prepara la stringa dati da inviare • la appende al ? nel modo previsto
I MODULI (FORM) Qui si scrive il testo da inviare al programma Quando si preme il bottone, il testo viene inviato
MODULI... E RISULTATI La stringa inviata ha una forma particolare:Campo=Valore Riscrive esattamente la stringa ricevuta
RISULTATI... E MODULI Questo campo di testo si chiamava testo Perciò, la stringa inviata è statatesto=PaolinoPaperino Il testo scritto era PaolinoPaperino
IL MODULO (HTML) <TITLE> Esempio di form </TITLE> <H1> Esempio di form </H1> <FORM METHOD="GET"ACTION="http://localhost/cgi/enrico/prova0.exe" > Inserisci il testo:<INPUT NAME="testo"> e poi premi invio:<INPUT TYPE="submit" VALUE="invio"> </FORM> Protocollo GET Azione da compie-re quando si preme il pulsante invio
IL MODULO (HTML) <TITLE> Esempio di form </TITLE> <H1> Esempio di form </H1> <FORM METHOD="GET"ACTION="http://localhost/cgi/enrico/prova0.exe" > Inserisci il testo:<INPUT NAME="testo"> e poi premi invio:<INPUT TYPE="submit" VALUE="invio"> </FORM> Il campo di testo (di nome testo) Il pulsante che attiva l’azione (tipo submit), chiamato invio nel modulo
INVIO DI DATI CON I MODULI • Dunque, quando si compila un modulo, la stringa inviata al programma (con GET) ha sempre la forma standard seguente: ...?nome1=valore1&nome2=valore2&... dove • nome1,nome2, ... sono i nomi dei campi (di testo, di selezione,...) • valore1,valore2, ... sono i testi effetti-vamente scritti nei rispettivi campi
UN MODULO PIÙ COMPLESSO Due campi di testo, deno-minati rispettivamente Nome e Cognome Due pulsanti, chiamati conferma e annulla(il primo invia, il secondo cancella il modulo)
IL RISULTATO La stringa inviata ha la forma standardNome=Paolino&Cognome=Paperino
IL MODULO PIÙ COMPLESSO (HTML) Un diverso programma <H1> Esempio di form </H1> <FORM METHOD="GET" ACTION="http://localhost/cgi/prova1.exe" > Inserire i seguenti dati:<p> Inserire il nome: <INPUT NAME="Nome"><br> Inserire il cognome: <INPUT NAME="Cognome"> <p> <INPUT TYPE="submit" VALUE="conferma"> <INPUT TYPE="reset" VALUE="annulla"> </FORM> i due campi di testo i due pulsanti (il tipo submit invia, il tipo reset cancella il modulo)
IL PROGRAMMA Il programma riceve una stringa in forma standard e deve estrarre i vari pezzi main(){ char cognome[80], nome[80], *st; printf("Content-type: text/plain\n\n"); st = getenv("QUERY_STRING"); estrai(st, "Nome", nome); estrai(st, "Cognome", cognome); printf("Buongiorno %s %s!\n\n", nome, cognome); } I nomi dei campi di testo del modulo (attenzione: devono essere identici!)
IL PROGRAMMA La funzione estrai(char*, char*, char*) int estrai(char s[], char parametro[], char valore[]) { const char separatore = '&'; char *fine, *pos = strstr(s,parametro); if (pos==NULL) return 1; /* non c’è */ pos += strlen(parametro)+1; fine = strchr(pos,separatore); if (fine==NULL) fine = pos + strlen(pos); strncpy(valore,pos,fine-pos); valore[fine-pos]='\0'; return 0; }
IL PROGRAMMA La funzione estrai(char*, char*, char*) int estrai(char s[], char parametro[], char valore[]) { const char separatore = '&'; char *fine, *pos = strstr(s,parametro); if (pos==NULL) return 1; /* non c’è */ pos += strlen(parametro)+1; fine = strchr(pos,separatore); if (fine==NULL) fine = pos + strlen(pos); strncpy(valore,pos,fine-pos); valore[fine-pos]='\0'; return 0; } parametro=valoreci si posiziona dopo l’= parametro=valore&si cerca l’& finale (se c’è) finalmente si ricopia in valore il pezzo che serve se l’& finale non c’è, si prende fino a fine stringa
Da GET a POST • Finora, per inviare dati al programma CGI abbiamo sfruttato il sub-protocollo GET • Pro: è semplice, è facile da gestire • Contro: è inadatto a inviare molti dati (la varia-bile QUERY_STRING ha limiti di lunghezza) • Questi limiti si superano con ilsub-proto-collo POST • i dati sono inviati sullo standard input del programma • richiede obbligatoriamente un modulo (form) per inviare i dati (non si possono appendere all’URL)
INVIO DI DATI con POST • È indispensabile usare un modulo (form) • Quando si preme il pulsante di invio, il browser invia i dati al server... • .. che li ridirige sul canale d’input standard del programma • i dati si possono quindi recuperare con normali letture da input • non si passa più dalle variabili di ambiente del sistema operativo, quindi non ci sono limiti di dimensione
INVIO DI DATI con POST Quale formato usa POST per inviare i dati? • di norma, usa lo stesso formato di GET: nome1=valore1&nome2=valore2&... • Se però si specifica un particolare tipo di codifica (enctype), il browser usa quello • Ad esempio, con enctype="multipart/form-data”il browser invia i dati su righe separate, uno per riga, separati da righe speciali e righe vuote.
LO STESSO MODULO DI POCO FA Due campi di testo, deno-minati rispettivamente Nome e Cognome Due pulsanti, chiamati conferma e annulla(il primo invia, il secondo cancella il modulo)
...CHE USA POST (CASO BASE) Un terzo programma <H1> Esempio di form </H1> <FORM METHOD="POST" ACTION="http://localhost/cgi/prova2.exe" > Inserire i seguenti dati:<p> Inserire il nome: <INPUT NAME="Nome"><br> Inserire il cognome: <INPUT NAME="Cognome"> <p> <INPUT TYPE="submit" VALUE="conferma"> <INPUT TYPE="reset" VALUE="annulla"> </FORM>
IL PROGRAMMA Il programma fa l’eco di tutto ciò che riceve: main(){ char buf[1024]; printf("Content-type: text/plain\n\n"); printf("Risposta:\n\n"); while(gets(buf)) printf("%s\n", buf); } Ipotesi: righe non più lunghe di 1024 caratteri
IL RISULTATO (NEL CASO BASE) Niente più dati appesi all’URL La stringa inviata ha la forma standardNome=Paolino&Cognome=Paperino
IL POST “multipart/form-data” Lo stesso programma <H1> Esempio di form </H1> <FORM METHOD="POST" ACTION="http://localhost/cgi/prova2.exe" enctype="multipart/form-data"> Inserire i seguenti dati:<p> Inserire il nome: <INPUT NAME="Nome"><br> Inserire il cognome: <INPUT NAME="Cognome"> <p> <INPUT TYPE="submit" VALUE="conferma"> <INPUT TYPE="reset" VALUE="annulla"> </FORM> Una diversa codifica
... E IL DIVERSO RISULTATO I dati sono inviati uno per riga, separati da righe speciali e da una riga vuota
IL CODICE FISCALE.. SUL WEB!! Ricordate l’esercizio sul codice fiscale? • una delle varianti prevedeva proprio il formato di dati tipico di GET e POST (caso base) • adottando tale formato di input, il program-ma può essere “portato sul Web” senza sforzo... • ...e immediatamente un servizio importante risulta disponibile a tutti!