SPEAKER: Acum să se arunca cu capul în codul de distribuție și să ia o privire la contextul în care codul pe care îl scrie va fi de operare. La sfârșitul zilei, ai de gând să pună în aplicare totalitatea serverul de web. Dar ne-am asigurat tu cu scheletul cod care au putea funcționa, în special legate de rețea. Să aruncăm o privire. Deci, aici spre partea de sus a dosarului este un buchet de facilitate de testare cerințelor macro. Acum, aceasta este doar o trăsătură de c, prin care în conformitate cu o grămadă de pagini man trebuie să definiți unele din aceste constante să fie adevărat sau să fie chiar anumite numere, astfel încât aveți acces la anumite funcții. În caz contrar, acestea vor fi nedeclarate și nu veți avea acces. Așa că am făcut acest lucru prin fel de a citi paginile de manual. Acum jos, în Liniile 15 și 17, noi au o grămadă de limite declarate. Și am împrumutat acestea la un server web popular numit Apache. Și acestea sunt doar Numerele care vor să limiteze numărul total de bytes care sunt permise în diverse contexte pentru cererea HTTP că un browser este permis să-mi trimită. Mai departe, vom defini octeti. Acum, un octet este doar un mod de lux de a spune un octet, sau opt biți. Se pare că într-odinioară un octet Nu a fost necesar opt biți, așa octet este întotdeauna opt biți. Deci, în acest caz, am adoptat ceea ce este comun în rețea lume de asteptare opt octeti un octet. Aici am precizat că octeti va fie 512, astfel încât de mult ca în criminalistica când am citit o grămadă de bytes la un moment dat, aici, vom citi o buchet de octeti la un moment dat. Mai departe o grămadă de fișiere antet. Cum știu să includă astea? Ei bine, am citit pur și simplu omul pagini pentru un număr de funcții că vom folosi în această distribuție cod și să includă în cele Am fost instruit să. Și acum avem un tip de date. Am declarat un octet a fi un char. Și vom vedea mai târziu că este utilizate în întreaga codul. Și am declarat un grămadă de prototipuri, și vom plimba rapid prin fiecare dintre aceste funcții. În cele din urmă, și, probabil, cel mai important să se țină minte în acest moment în povestea, este că nu există sunt, de fapt, un întreg grămadă de variabile globale în partea de sus a fișierului, rădăcină, CFD, SFD, cerere, fișier și corp. Acum, în general, folosind atât de multe la nivel mondial variabile, sau variabile globale la toate, nu este practica spate. Dar se pare că suntem, de asemenea, cu ajutorul unui Manipularea semnal tehnica numita mai târziu în codul, ceea ce ne permite să detecta atunci când utilizatorul hit-uri ceva ca CTRL C și închide serverul grațios. Și pentru a face asta cu grație și de fapt a elibera memorie, trebuie să avem acces la aceste variabile globale. Și acum să aruncăm o privire la principal, care conduce ansamblul acestui program. În primul rând, în partea de sus de aici noi au un număr variabil de eroare care pare a nu au un tip, dar asta e pentru că este de fapt definite într-un fișier numit Eroare errno.h care este inclus în sus mai mare. Dacă veți face om errno la efectiv a se vedea definiția de acest lucru, veți vedea că aceasta este o Global variabilă special, care este stabilit de o grămadă funcțiilor nu scrise de noi, ci de autorii Linux și alte sisteme pentru a stabili efectiv un număr de care variabil, atunci când ceva nu merge bine, astfel încât să puteți la nivel global dau seama ce a făcut merge prost. Acum mai jos veți vedea o nouă Tehnica probabil folosind getopt, o funcție care ajută comanda analizare argumente în linia de astfel încât să nu Trebuie să deranjeze timp pierdem imaginind cum pentru a analiza ceva de genul 8080, sau cratimă p, sau liniuță h pentru a obține ajutor. getopt face, în esență, că pentru noi. Consultați pagina de manual pentru mai multe. Mai departe, vom face un pic de eroare de verificare pentru a vă asigura că numărul de port este în intervalul specificat în spec. Mai departe, vom vedea o chemare la funcția începe, a cărui definiție vom uita-te la într-un moment, și ca numele său sugerează, aceasta începe serverul de web. Aici avem un apel la o funcție numit semnal care spune, dacă și atunci când auzi de control C de la tastatură utilizatorului, mergeți mai departe și de apel un handler funcție numită ce se intampla lucruri pentru a curăța în cele din urmă în sus și opri serverul. Mai jos, care este ceea ce pare a fi o buclă infinită, din care prima linie eficient este un apel la o funcție numită reseta, care ne-am punerea în aplicare a mai târziu, în ordine pentru a elibera o parte din statele noastre globale. După aceea este o linie de cod care condiționat verifică revenirea Valoarea de conectat. Arata acum conectate, cum ar fi un predicat, ceva care returnează adevărat sau fals. Și o face, dar nu e ceva special în conectat prin aceea că este un apel de blocare. Acesta va sta acolo și să aștepte până la browser-ul unui utilizator încearcă să se conecteze la acest web serverul și numai atunci va întoarce adevărat sau fals, astfel încât să continuăm în interiorul acestui if. Odată ajunși acolo, observa această funcție într-o funcție numită parse, pe care am scris, care analizează toate octeti, toate de bytes care provin dintr-un browser la server, astfel încât să putem preda te-ai întors în cele din urmă o valoare de un de aceste variabile globale care stochează toate de octeți în doar anteturile de care cerere, nu corpul dacă ar exista de fapt un corp de ea. Acum mai jos vom începe să analiza aceste antete pentru a extrage un subset al informațiilor că ne pasă. Mai exact, pe caietul de sarcini, noi mai întâi a vrut să solicite linie, care este doar că prima linie care sperăm spune ceva de genul get slash sau unele cale și apoi HTTP 1.1. Suntem folosind acest metaforă de un ac in carul cu fan să caute special caractere sau adrese. Și într-adevăr, există un număr de funcții în codul nostru de distributie pe care le, de asemenea, s-ar putea găsi de ajutor atunci când caută pentru valorile particulare. În cele din urmă, am copia aceste bytes într-o linie variabilă numită, care observa, de asemenea, ne-am alocate pe stivă prin intermediul unei matrice de dimensiuni dinamic. Și suntem în mod deliberat încearcă pentru a evita apelarea malloc deoarece din nou, deoarece de control C fiind o caracteristică potențial a acestui program, ne-am nu doresc să aibă acest cod brusc întreruptă de lovirea utilizator Controlul C, al cărei rezultat este că s-ar putea să nu aibă o șansă pentru ceva gratuit am malloced. Așa că am încercat să folosească cât mai mult stivei este pot aici. Următorul, o grămadă de la dos. Caietul de sarcini va expune pe exact ceea ce se așteaptă aici, dar comentariile pe care le dau un indiciu a ceea ce se află în fața. Mai întâi trebuie să valida linia cerere și asigurați-vă că se pare că caietul de sarcini gramatica, ca să spunem așa, spune că ar trebui. Apoi nevoie pentru a extrage ceva numit interogare, chestii afară după un semn de întrebare, cum ar fi am văzut cu exemplul nostru Google în treacăt într-un parametru HD. Apoi înlănțui împreună rădăcina serverului web cu calea pe care se află într- această cerere primul rând și formează calea completă a fișierul vrem să căutăm. După aceea, vom să ne asigurăm că fișierul există și este lizibil. Și apoi vom extrage sale extensie de fișier, .html sau .php, sau o astfel de prelungire care, la foarte capăt șirului solicitate. Următorul este un întreg grămadă de cod am scris pentru a genera fapt PHP generat de conținut pentru tine. Într-un cuvânt, aceasta cod are în numele din fișierul pe care doriți PHP să interpreteze. Am trece prin ceva numit o țeavă în interpret PHP. Du-te înapoi răspunsul ca și cum răspunsul a fost un fișier în sine. Și apoi ne repeta peste care fișier bytes, trăgând-le pe toate într-un singur tampon astfel încât să putem în cele din urmă printeaza-le. Într-adevăr, toate acestea solicită aici pentru a dprintf ne permite să imprimați ceva numit un descriptor de fisier, care este doar un număr întreg care reprezintă un fișier. Foarte asemănător în spirit, dar fundamental diferit de la un fișier pointer stele. Observați modul în care puteți utiliza sintaxă ca printf aici așa că pot dinamic introduce ceva de genul lungimea pentru valoarea afara HTTP numit Content-Length. Și în cele din urmă am folosit Funcția dreptul de a scrie de fapt corpul cererii. Din păcate, ne-am pus în aplicare doar sprijin pentru dinamic fișierele PHP generate. Nu am în aplicare de sprijin pentru Fișierele statice, cum ar fi gif-uri, și JPEG, și CSS și HTML fișiere. Asta, din păcate, este lăsată la tine a răspunde scopului client asta face. Deci, acolo veți găsi că există nu de mult inspirație în acest bloc, dar dacă un pic mai mare de până la modul în care ne-am dus despre interpretarea cod PHP, funcțiile veți utiliza sunt un pic diferit. De fapt, puteți împrumuta parte din funcționalitatea probabil de la criminalistica set problemă, pentru că la sfârșitul zilei tot ce ai nevoie pentru a face aici este din ce stiti ce fișier deschis și odată ce știi că e așa-numitele Tip MIME sau tip de conținut, aveți nevoie pentru a citi în aceste octeți și într-un fel le scuipe înapoi. Și acum un tur al acestui alte funcții fișierului. Până în primul rând este conectat, care pur și simplu returneaza true când se aude în cele din urmă o conexiune de la un utilizator. Următorul este eroare. Eroare, între timp, așa cum o vom funcție a scris să se ocupe de toate de diferite 400 și statutul 500 HTTP coduri care v-ar dori pentru a trimite înapoi la utilizator, împreună cu un mesaj standard. Următorul este de sarcină, un deosebit de Funcția miez, al cărui scop în viață este de a citi dintr-un fișier stea Pointer conținutul unui fișier într-un tampon global că noi declarat la nivel global de mai sus [? principal. ?] Acesta este un complex pic pentru că noi Trebuie să citiți octeți din fișierul dar verifica pe fiecare iterație dacă ne-am deja lovit la sfârșitul fișierului sau altceva a mers prost. Și vom folosi realloc pentru a vă asigura că indiferent de tampon folosim este în creștere și în creștere și în creștere și mereu stau in partea din numărul de octeți că avem nevoie pentru a se potrivi acolo. Handler, între timp, este funcția care devine numit prin cale de a avea înregistrată control C ca un semnal pe care dorim să intercepteze. Observați aici în handler că în cele din urmă solicită opri, care, desigur, oprește serverul de web. Și, din păcate, căutare nu este pusă în aplicare. În spirit, aceasta este o Funcția destul de simplu. Având în vedere o extensie de fișier, are nevoie de pentru a reveni se așa-numitele MIME tip sau tip de conținut. Și am să precizeze în caietul de sarcini ceea ce trebuie să fie cea de cartografiere. Dar trebuie să traduce se în cele din urmă cu codul C. Următorul este funcția noastră la fel de miez numit parse, al cărui scop în viață este de a citi, nu dintr-un fișier, ci de la o conexiune la rețea. Mai exact, citind și parsarea Cerere HTTP care a venit dintr-un browser la server, astfel încât în cele din urmă, putem analiza la doar antetele din cererea de line și să se întoarcă pe cei la tine prin intermediul unui tampon globală care am declarat mai sus [? principal. ?] Reset, între timp, este o funcție care definim că este chemat iterativ interior de principal de fiecare dată când ești pe cale gata să înceapă de ascultare pentru o nouă conexiune astfel încât să știm mereu starea de variabilele și astfel încât ne-am, de asemenea, eliberat orice amintire care ar fi fost alocate pentru o conexiune la rețea anterior. Următorul este pornește, funcție care am scris care conține un întreg mulțime de cod de rețea care incep in cele din urma serverul de web. Ultima sus este funcția numita oprire, care face exact acest lucru, oprește serverul de web. Dar mai întâi se eliberează nici o amintire care încă au fost alocate. Dar în cele din urmă solicită ieșire chiar și fără returnarea de control funcției nostru principal. În cele din urmă, unul dintre majoritatea tehnicilor importante la punerea în aplicare acest server web este Va fi un pic de studiu și de eroare, având una browser fereastră deschisă la dreapta și o fereastră terminal la stânga, consola servere fereastră, astfel încât să Puteti vedea mesajele care sunt fiind afișate pe ecran. Dar mai bine ar fi un al treilea fereastră, o fereastră terminal al doilea, în care utilizați Telnet, utilizarea pentru care este prescris în spec. Și Telnet este doar o foarte Programul rețea simplu care vă permite să pretinde la fi un browser intr-unul fereastră în timp ce vorbesc la cealaltă fereastră. În acest fel puteți vedea exact comenzile textuale care se întorc de la server la client fără a fi nevoie să poking în jurul valorii de dezvoltator Chrome Unelte într-un alt mod interfață clunkier.