SPEAKER: Nå la oss dykke i fordelingen kode og ta en titt på sammenhengen der koden du skriver kommer til å være i drift. På slutten av dagen, du kommer til å implementere helheten av webserveren. Men vi har gitt du med skjelettet kode som har noen funksjonalitet, spesielt relatert til nettverk. La oss ta en titt. Så her oppe mot toppen av filen er en gjeng av funksjonen teste makro krav. Nå er dette bare en funksjon av c, der ifølge en haug av man-sidene du må definere noen av Disse konstantene til å være sann eller å være enda konkrete tall slik at du har tilgang til visse funksjoner. Ellers vil de bli svart og du vil ikke få tilgang. Så jeg har gjort dette ved hjelp av å lese man-sidene. Nå ned nedenfor, i linjene 15 til og med 17, vi har en hel haug av område deklarert. Og vi har lånt disse fra en populære web-server som heter Apache. Og dette er bare tallene som kommer til hetten det totale antall byte som er tillatt i ulike sammenhenger for HTTP-forespørsel at en nettleser er lov til å sende meg. Deretter definerer vi oktetter. Nå en oktett er bare en fancy måte si en byte, eller åtte biter. Det viser seg at i gamle dager en byte var ikke nødvendigvis åtte bits, så oktett er alltid åtte biter. Så i dette tilfellet har vi vedtatt hva som er vanlig i nettverk verden for å ringe åtte byte en oktett. Her har jeg presisert at oktetter vil være 512, slik at mye som i etterforskning når vi leser en haug med byte om gangen, og også her vi kommer til å lese en haug med oktetter gangen. Neste en hel haug med header filer. Hvordan visste jeg å inkludere disse? Vel jeg bare lese mannen sider for en rekke funksjoner at vi vil bruke i denne fordelingen kode og omfatter i de Jeg ble instruert til. Og nå har vi en datatype. Vi har erklært en oktett å være en røye. Og vi skal se senere at det er brukes i hele koden. Og vi har erklært en hel haug med prototyper, og vi vil gå raskt gjennom hver av disse funksjoner. Til slutt og kanskje mest viktig å huske på tankene på dette punktet i historien, er at det er, faktisk en hel haug av globale variabler ved toppen av filen, rot, CFD, SFD, forespørsel, fil og kropp. Nå generelt, ved hjelp av så mange globale variabler, eller globale variabler i det hele tatt, ikke er tilbake praksis. Men det viser seg at vi også bruker en teknikk kalt signalhåndtering senere i koden, som tillater oss å oppdage når brukeren treffer noe som CTRL C og stenge ned serveren grasiøst. Og for å gjøre det grasiøst og faktisk frigjøre minne, vi trenger å ha tilgang til disse globale variabler. Og nå la oss ta en titt på main, som driver helheten av dette programmet. Først, på toppen her vi har et feilnummer variabel det synes ikke å har en type, men det er fordi det er faktisk definert i en fil som heter error errno.h som er inkludert høyere opp. Hvis du gjør mennesket errno å faktisk se definisjon for denne tingen, vil du se at dette er en spesiell global variabel som er satt av en hel haug funksjoner ikke skrevet av oss, men av forfatterne av Linux og andre systemer for å faktisk sette et nummer til den variabelen når noe går galt, slik at du kan globalt finne ut hva som gikk galt. Nå ned under vil du se en ny teknikk kanskje ved hjelp getopt, en funksjon som hjelper analysere kommando argumenter, slik at vi ikke gjør det å bry kaste bort tid på å finne ut hvordan å analysere noe som 8080, eller dash p, eller dash h for å få hjelp. getopt egentlig gjør det for oss. Se man-siden for mer. Neste, vi gjør litt av feil kontrollerer at at portnummeret er innenfor det angitte området i spec. Deretter ser vi et kall til funksjonen starte, der definisjonen vi vil se på i et øyeblikk, og som navnet antyder, dette starter webserveren. Her har vi en samtale til en funksjon kalt signal som sier, hvis og når du hører kontroll C fra brukerens tastatur, gå videre og kaller en funksjon som heter handler som kommer til slutt rene ting opp og stoppe serveren. Under dette er det som synes å være en uendelig løkke, den første linjen i hvilken er effektivt en samtale til en funksjon som kalles reset, som vi selv implementere senere i orden å frigjøre noen av våre globale stater. Etter at det er en linje av kode som betinget sjekker avkastningen Verdien av tilkoblede. Nå koblet ser ut som et predikat, noe som returnerer sant eller usant. Og den gjør det, men det er noe spesielt i tilkoblet i at det er en blokkering samtale. Det vil sitte der og vente inntil en brukers nettleser prøver å koble til denne web server og først da vil det returnere sant eller usant, slik at vi går videre på innsiden av dette hvis setningen. Når du er der, legge merke til denne funksjonen til en funksjon kalt parse, som vi skrev, som analyserer alle de oktetter, alt av bytes som kommer fra en nettleser til serveren, slik at vi kan levere du tilbake til slutt en verdi til en av de globale variabler som lagrer alle av byte i bare hodene av det forespørsel, ikke legemet Hvis det var faktisk en kropp til den. Nå nede begynner vi å analysere disse overskrifter for å trekke ut et delsett av informasjonen at vi bryr oss om. Spesifikt, per spesifikasjon, vi først ønsket å be om linjen, som er nettopp det aller første linje som forhåpentligvis sier noe sånt som get slash eller noen sti og deretter HTTP 1.1. Vi bruker denne metaforen av en nål i en høystakk å lete etter bestemte chars eller adresser. Og ja, det er en rekke funksjoner i vår distribusjon kode at du også kan finne nyttig når vi leter etter bestemte verdier. Til syvende og sist, kopierer vi disse bytes inn i en variabel kalt linje, som legger merke til, også, vi har fordeles på stakken ved hjelp av en dynamisk størrelse array. Og vi bevisst prøver å unngå å kalle malloc fordi igjen, fordi av kontroll C blir en potensiell funksjon i dette programmet, vi ønsker ikke å ha denne koden plutselig avbrutt av brukeren treffer Kontroll C, hvor resultatet er at jeg ikke kan ha en sjanse gratis noe jeg har malloced. Så jeg prøver å bruke så mye av stabelen er jeg kan her. Neste opp, en hel haug med til dos. Spesifikasjonen vil forklare på nøyaktig hva som forventes her, men kommentarene gi deg et hint om hva som ligger foran oss. Du må først validere forespørsel linje og sørge for at det ser ut som spesifikasjoner grammatikk, så å si, sier det skal. Du må deretter å trekke ut noe kalt spørringen, ting ut etter et spørsmålstegn, som vi så med vår Google eksempel i forbifarten i en HD-parameter. Vi deretter sette sammen sammen roten av webserveren med banen som er i forespørselen første linje og danne den fullstendige banen filen vi ønsker å se etter. Deretter kommer vi til å sørge for at at filen finnes og er lesbare. Og så kommer vi til å trekke sin filtype, .html eller php, eller noe slikt utvidelse som er på Helt på slutten av strengen spurt. Neste opp er en helt haug med kode vi skrev å faktisk generere PHP generert innhold for deg. I et nøtteskall, dette kode tar i navnet av filen du vil PHP å tolke. Vi passerer det noe som heter et rør inn i PHP tolk. Få tilbake responsen som om responsen var en fil selv. Og da vi iterere over at filens byte, trekke dem alle i en buffer slik at vi kan til slutt skrive dem ut. Faktisk er alle disse kaller her for å dprintf tillater oss å skrive ut noe kalles en fil descriptor, som er bare et heltall som representerer en fil. Svært like i ånden, men fundamentalt forskjellig fra en fil stjerners pekeren. Legg merke til hvordan du kan bruke syntaks som printf her, slik at jeg kan dynamisk sette noe sånt som lengden for verdien av en HTTP-header kalt Content-Length. Og til syvende og sist jeg brukte den funksjon rett til å faktisk skrive legemet til forespørselen. Dessverre, vi bare implementert støtte for dynamisk genererte PHP-filer. Vi gjorde ikke implementere støtte for statiske filer som GIF og JPEG-bilder, og CSS og HTML-filer. Som dessverre er overlatt til deg for å svare til klienten formål Dette for å gjøre. Så i det du vil finne at det er ikke mye inspirasjon innenfor denne blokken, men hvis du litt høyere opp på hvordan vi gikk om tolking PHP-kode, funksjonene du vil bruke er litt annerledes. Faktisk kan du låne noe av funksjonaliteten kanskje fra etterforskning Problemet sett, fordi på slutten av dagen alt du trenger å gjøre her er når du vet hva filen åpen og når du vet det er såkalt MIME-type eller innholdstype, du trenger å lese i disse bytes og noe spytte dem ut igjen. Og nå en gjennomgang av dette filens andre funksjoner. Opp først er tilkoblet, som rett og slett returnerer true når det endelig hører en forbindelse fra en bruker. Neste opp er feil. Feil, i mellomtiden, som en funksjon vi skrev til å håndtere alle de ulike 400 og 500 HTTP status koder som du kanskje vil å sende tilbake til brukeren, sammen med en standardmelding. Neste opp er belastning, en spesielt meaty funksjon, hvis formål i livet er å lese fra en fil stjerne pekeren den innholdet i en fil inn i en global buffer at vi erklært globalt ovenfor [? Hoved. ?] Dette er litt komplisert fordi vi må lese byte fra filen men sjekk på hver iterasjon om vi har allerede treffer enden av filen eller noe annet har gått galt. Og vi bruker realloc å sørge for at uansett buffer vi bruker vokser og vokser og vokser og alltid bor i forkant av antall byte at vi trenger å passe inn der. Handler, i mellomtiden, er den funksjon som får heter i form av å ha registrert Kontroll C som en signal at vi ønsker å fange opp. Legg merke til her i behandleren at det til syvende og sist anrop stoppe, noe som selvsagt stopper webserveren. Og dessverre, oppslag er ikke implementert. I ånden, er dette en ganske enkel funksjon. Gitt en filtype, må det å returnere det såkalte MIME type eller innholdstype. Og vi angir i spesifikasjonen hva som kartlegging må være. Men du trenger å oversette det til slutt til c-kode. Neste opp er vår tilsvarende kjøttfulle funksjon kalt parse, hvis formål i livet er å lese, ikke fra en fil, men fra en nettverkstilkobling. Spesifikt, lesing og analyse av HTTP-forespørsel som har kommet fra en nettleser til serveren, slik at til slutt kan vi analysere på bare overskriftene i forespørselen linje og returnere dem til deg ved hjelp av en global buffer som vi erklært ovenfor [? Hoved. ?] Tilbakestill, i mellomtiden, er en funksjon som vi definerer som blir kalt iterativt inne av hoved hver gang du er i ferd klar til å begynne å lytte for en ny tilkobling slik at vi alltid vet staten av våre variabler og slik at vi har også frigjort noe minne som kan ha blitt avsatt til en tidligere nettverkstilkobling. Neste opp er starte, funksjon som vi skrev som inneholder en hel Mange nettverk koden som til slutt starter webserveren. Siste opp er funksjonen heter Stopp, som gjør akkurat det, det stopper webserveren. Men først er det frigjør noe minne har det likevel blitt tildelt. Men det krever slutt exit uten selv tilbake kontrollen til vår viktigste funksjon. I siste instans én av de fleste viktige teknikker når du implementerer denne web server er kommer til å være litt prøving og feiling, ha en nettleservindu åpent til høyre og et terminalvindu på venstre, servere konsoll vindu, slik at du kan se meldingene som er som vises på skjermen. Men enda bedre ville være en tredje vinduet, en andre terminal vindu, der du bruker Telnet, bruken som er foreskrevet i spec. Og Telnet er bare en veldig enkel nettverksprogram som lar deg å late som være en nettleser i ett vindu mens du snakker til det andre vinduet. Denne måten kan du se nøyaktig de tekstlige kommandoer som kommer tilbake fra server til klient uten å måtte poking rundt krom utvikleren verktøy i en ellers clunkier grensesnitt.