SPEAKER: Ora diamo immersione nel codice di distribuzione e dare un'occhiata al contesto in cui il codice si scrive sta per essere operativo. Alla fine della giornata, si sta andando a implementare la totalità del server web. Ma abbiamo fornito con lo scheletro codice che hanno alcune funzionalità, soprattutto relative al networking. Diamo uno sguardo. Così qui verso l'alto del file è un po ' di funzionalità di testare requisiti macro. Ora, questo è solo una caratteristica di c, per cui secondo un gruppo di pagine man è necessario definire alcuni dei queste costanti per essere vero o di essere addirittura numeri specifici in modo che si ha accesso a determinate funzioni. In caso contrario, essi saranno SOMMERSO e non avrete accesso. Quindi ho fatto questo titolo di leggere le pagine di manuale. Ora in basso, in linee 15 a 17, si hanno un sacco di limiti dichiarati. E abbiamo preso in prestito questi da un popolare web server chiamato Apache. E questi sono solo numeri che sono in corso di limitare il numero totale di byte che sono ammessi in vari contesti della richiesta HTTP che un browser può inviare me. Avanti, definiamo ottetti. Ora un ottetto è solo un modo di fantasia di dire un byte, o otto bit. Risulta in passato un byte non era necessariamente otto bit, così ottetto è sempre otto bit. Quindi, in questo caso, abbiamo adottato ciò che è comune nella rete mondo di chiamare otto byte un ottetto. Qui ho specificato che sarà ottetti essere 512, in modo che tanto come in medicina legale quando leggiamo un gruppo di byte alla volta, anche qui, stiamo andando a leggere un mazzo di ottetti alla volta. Avanti tutta una serie di file di intestazione. Come facevo a sapere di includere questi? Beh ho semplicemente letto l'uomo pagine per un certo numero di funzioni che useremo in questa distribuzione codice e include in quelli Sono stato incaricato di. E ora abbiamo un tipo di dati. Abbiamo dichiarato un ottetto di essere un char. E vedremo in seguito che questo è utilizzato in tutto il codice. E abbiamo dichiarato un tutta una serie di prototipi, e noi cammineremo rapidamente attraverso ciascuna di queste funzioni. Infine, e forse più importante tenere a mente a questo punto la storia, è che non c'è sono, infatti un intero gruppo di variabili globali nella parte superiore del file, radice, CFD, SFD, richiesta, di file e il corpo. Ora in generale, con tanti globale variabili o variabili globali a tutti, non è la pratica di nuovo. Ma si scopre che stiamo utilizzando anche un tecnica chiamata gestione del segnale più tardi nel codice, che ci permette di rilevare quando l'utente preme qualcosa come CTRL C e si spegnerà il server con grazia. E per farlo con grazia e in realtà liberare memoria, abbiamo bisogno di avere accesso a queste variabili globali. E ora diamo uno sguardo al principale, che spinge l'interezza di questo programma. Innanzitutto, nella parte superiore qui avere un numero variabile di errore che appare di non avere un tipo, ma questo è perché in realtà è definito in un file chiamato errore che errno.h è incluso più in alto. Se fate uomo errno effettivamente vedi la definizione per questa cosa, vedrete che questo è un speciale variabile globale che è impostato per un intero gruppo di funzioni non scritta da noi, ma da Linux autori e altri sistemi per impostare effettivamente un numero di variabili che quando qualcosa va storto in modo che possiate globale capire cosa ha fatto andare storto. Ora in basso vedrete una nuova tecnica magari utilizzando getopt, una funzione che aiuta il comando parse gli argomenti della riga in modo che non facciamo devono preoccuparsi perdite di tempo per capire come analizzare qualcosa come 8080, o un trattino p, o trattino h per ottenere aiuto. getopt fa in sostanza, che per noi. Vedere la pagina man di più. Avanti, facciamo un po 'di errore controllo per assicurarsi che che il numero di porta è entro l'intervallo specificato nelle specifiche. Successivamente, vediamo una chiamata alla funzione avviare, la cui definizione ti guardare in un momento, e come il suo nome suggerisce, questo avvia il server web. Qui abbiamo una chiamata a una funzione chiamato segnale che dice: se e quando si sente di controllo C da la tastiera dell'utente, andare avanti e chiamare un gestore funzione chiamata che sta andando cose da pulire definitiva e smettere il server. Sotto questo è quello che sembra essere un loop infinito, la prima linea di cui effettivamente è una chiamata ad una funzione chiamata reset, che ci siamo implementare successivamente per per liberare alcuni dei nostri stati globali. Dopo che è una linea di codice condizionale sta controllando il ritorno valore collegato. Ora sembra collegati come un predicato, qualcosa che restituisce vero o falso. E lo fa, ma non c'è qualcosa di speciale in collegato in che si tratta di una chiamata di blocco. Si siederà lì e aspettare fino browser di un utente tenta di connettersi a questo sito web server e solo allora sarà vero restituire true o false in modo che si proceda all'interno di questo if. Una volta lì, notare questa funzione per un funzione chiamata parse, che abbiamo scritto, che analizza tutti gli ottetti, tutte dei byte provenienti da un browser al server, in modo che si possa consegnare si torna in ultima analisi, un valore a uno di queste variabili globali memorizza tutti i byte in proprio le intestazioni di tale richiesta, non il corpo se ci fosse effettivamente un corpo ad esso. Ora in basso cominciamo a analizzare queste intestazioni per estrarre un sottoinsieme delle informazioni che ci sta a cuore. In particolare, per la specificazione, per prima voluto richiedere la linea, che è solo che prima linea speriamo che dice qualcosa come get tagliare o qualche percorso e quindi HTTP 1.1. Stiamo utilizzando questa metafora di un ago in un pagliaio cercare particolare caratteri o indirizzi. E in effetti, c'è un certo numero di funzioni nel nostro codice di distribuzione che anche voi, potrebbe trovare utile quando alla ricerca di valori particolari. In ultima analisi, copiamo questi byte in una linea variabile chiamata, che notiamo, troppo, abbiamo allocato sullo stack per mezzo di una matrice di dimensioni dinamicamente. E stiamo cercando deliberatamente per evitare di chiamare malloc perché ancora una volta, perché di controllo C essere una caratteristica potenzialità di questo programma, abbiamo non vogliono avere questo codice improvvisamente interrotto dal colpire utente Controllo C, il cui risultato è che potrei non avere una possibilità gratuitamente qualcosa che ho malloced. Così sto cercando di utilizzare il più dello stack è che posso qui. Next up, un intero gruppo di al dos. La specifica sarà esporre esattamente quello che ci si aspetta qui, ma i commenti che danno un accenno di quello che ci aspetta. Innanzitutto è necessario convalidare la linea di richiesta e assicurarsi che sembra che il specifiche grammatica, per così dire, dice che dovrebbe. È quindi necessario estrarre qualcosa chiamato la query, la roba dopo un punto interrogativo, come abbiamo visto con il nostro esempio Google di passaggio in un parametro HD. Abbiamo poi concateniamo insieme la radice del server web con il percorso che è in tale richiesta prima linea e formare il percorso completo il file che vogliamo cercare. In seguito, stiamo andando a fare in modo che il file esiste ed è leggibile. E poi andremo a estrarne il estensione del file, .html o .php, o qualche tale estensione che è alla molto fine della stringa richiesto. Next up è un intero mucchio di codice che abbiamo scritto di generare realmente PHP generated content per voi. In poche parole, questo codice prende il nome del file che si desidera PHP interpreti. Noi passiamo da qualcosa chiamato un tubo in interprete di PHP. Tornate la risposta, come se la risposta fosse un file stesso. E poi iterare su tale file di byte, li tirano in un buffer in modo che possiamo in definitiva stamparli. Infatti, tutti questi chiamate qui per dprintf ci permette di stampare qualcosa chiamato un descrittore di file, che è solo un numero intero che rappresenta un file. Molto simile nello spirito, ma fondamentalmente diverso da un file puntatore stella. Notate come è possibile utilizzare la sintassi come printf qui in modo che io possa dinamicamente Inserire qualcosa come la lunghezza per il valore di un'intestazione HTTP chiamato Content-Length. E alla fine ho usato il Funzione diritto effettivamente scrivere il corpo alla richiesta. Purtroppo, abbiamo implementato solo Supporto per dinamicamente file PHP generati. Noi non implementare il supporto per file statici come GIF e JPEG, e file CSS e HTML. Questo, purtroppo, è lasciato a voi per rispondere allo scopo client questo per fare. Così in là troverete che non c'è non molto ispirazione all'interno di tale blocco, ma se un po 'più in alto di quanto siamo andati su interpretare codice PHP, le funzioni che useranno sono un po 'diverso. In realtà, si può prendere in prestito alcune delle funzionalità forse dalle forensics set problema, perché alla fine della giornata tutto ciò che serve a fare qui è una volta di sapere cosa file aperto e una volta che sai che è la cosiddetta Tipo MIME o tipo di contenuto, avete bisogno di leggere in quei byte e in qualche modo li sputare indietro. Ed ora un tour di questa altre funzioni del file. Fino primo è collegato, che restituisce semplicemente true quando finalmente sente un connessione da un utente. Next up è errore. Errore, nel frattempo, in funzione abbiamo ha scritto per gestire tutte le diverse 400 e lo stato HTTP 500 codici che si potrebbe desiderare rispedire per l'utente, insieme con un messaggio standard. Next up è carico, un particolare funzione carnosa, il cui scopo nella vita è quello di leggere da una stella di file puntatore del contenuto di un file in un buffer globale che abbiamo dichiarato a livello globale sopra [? principale. ?] Questo è un po 'complessa, perché ci devono leggere i byte dal file ma controllare ogni iterazione se abbiamo già colpire la fine del file o qualcosa è andato storto. E usiamo realloc fare in modo che qualunque tampone che stiamo usando è in crescita e in crescita e in crescita e sempre stare davanti il ​​numero di byte che abbiamo bisogno di adattarsi in là. Handler, nel frattempo, è la funzione che ottiene chiamato dal modo di avere registrati controllo C come segnale che vogliamo intercettare. Si noti qui in gestore che in ultima analisi, chiamate fermano, che naturalmente arresta il server web. E purtroppo, ricerca non è implementata. Nello spirito, questo è un funzione abbastanza semplice. Dato un estensione del file, è necessario per tornare è la cosiddetta MIME tipo o tipo di contenuto. E si precisa nella specifica cosa che la mappatura deve essere. Ma è necessario tradurre in ultima analisi, il codice c. Next up è la nostra funzione in modo simile carnosa chiamato parse, il cui scopo nella vita è da leggere, non da un file, ma da una connessione di rete. Lettura, particolare e l'analisi del Richiesta HTTP che è venuto da un browser al server in modo che in ultima analisi, siamo in grado di analizzare a soli le intestazioni nella richiesta linea e tornare quelli di voi per mezzo di un buffer globale abbiamo dichiarato in precedenza [? principale. ?] Reset, nel frattempo, è un funzione che definiamo che viene chiamato iterativamente dentro di principale ogni volta che si sta pronto per iniziare ad ascoltare per una nuova connessione in modo che sappiamo sempre lo stato delle nostre variabili e così che abbiamo anche liberata alcuna memoria potrebbe essere stato assegnato per una connessione di rete precedente. Il prossimo è avviare, il funzione che abbiamo scritto che contiene un intero sacco di codice di rete che inizia alla fine il server web. Ultimo up è la funzione chiamato stop, che fa esattamente questo, arresta il server web. Ma prima si libera la memoria che ancora è stato assegnato. Ma si chiede in definitiva uscita senza nemmeno restituire il controllo la nostra funzione principale. Infine, uno degli la maggior parte delle tecniche importanti in sede di attuazione questo server web è sarà un po 'di tentativi ed errori, avere una finestra aperta del browser a destra e una finestra terminale a sinistra, la console server finestra, in modo che può vedere i messaggi che sono la visualizzazione sullo schermo. Ma meglio ancora sarebbe un terzo finestra, una seconda finestra terminale, in cui si usa Telnet, l'uso per i quali è prescritto nelle specifiche. E Telnet è solo un semplice programma di rete che consente di far finta di essere un browser in una finestra mentre parlando l'altra finestra. In questo modo si può vedere esattamente i comandi testuali che stanno tornando dal server al client senza dover frugare intorno sviluppatore di Chrome utensili in un altrimenti clunkier interfaccia.