DAVID MALAN: Nå la oss ta en ser på den faktiske fordelingen kode i filen som heter server.c. Nå må du huske på at dette filens ganske stort denne uken. Det er over 1000 linjer med kode, men de fleste av disse linjene vi har skrevet. Og hva vi har igjen er noen blanks som du vil må fylle ut for å legge til noen av de mest oppsiktsvekkende funksjoner av webserveren å faktisk få det i gang. Faktisk, hvis du kjører distribusjon kode etter kompilering det du vil finne at webserveren gjør ikke så mye. I stedet får brukeren en 501, ikke implementert, feilmelding. Men det bør være fornuftig fordi vi har faktisk ikke implementert all sin funksjonalitet. Så la oss ta en titt på server.c. Og vil du ønsker å gå over dette i en litt mer detaljert litt saktere, i ditt eget tempo. Men for nå la meg prøve å veilede deg gjennom det å gi deg en følelse av hva som er nyttig å vet, hva som er mindre nyttig å vite, slik at du kan veilede din egen leting. Så på toppen av server.c, selvfølgelig, vi har en hel haug med definerer. I tillegg til en hel haug med inneholder. Verdt å merke seg er at vi har noen få globale konstanter her, som vi bruker i vår kode for å gjøre sikker på at visse arrays er av tilstrekkelig lengde. Basert på hvor lenge HTTP-forespørsler vi forvente å bli mottatt, potensielt, fra web-klienter, eller nettlesere. I mellomtiden, la oss rulle ned her, til én type definisjon. Legg merke til at akkurat som i P satt 4, hvor vi spilte med fil I / O, på samme måte her, vi er spiller med mye bytes. Og så har vi typedeffed char å være en byte. Med andre ord, den datatype, kapital B-y-t-e, ikke finnes som standard i C. Så vi har laget det som et synonym for røye, slik at vi har noen 8-bits verdi som å arbeide. Nå er det en hel haug med prototyper her, noen som er for funksjoner du vil skrive, men de fleste av dem vi har skrevet selv. La oss bla ned nå til slutt, bare noen få globale variabler. En er dette røye stjerne, AKA roten. Faktisk, vil du legge merke til at vi ikke er bruke CS50 biblioteket lenger. Så vi i stedet bare bruker røye stjerne. Og rot kommer til å være en peker til strengen som representerer roten til serveren. Så, for eksempel, når jeg kjørte kommandoen tidligere og spesifisert roten til "offentlig", som katalog innsiden av fordelings kode. Root, her, ville være en peker til akkurat strengen, "offentlig". Eller egentlig hele banen / home / ubuntu / så videre til at offentlig katalog. I mellomtiden, i tråd 67 her, har vi det som kalles fildeskriptorer. Disse ligner i ånden til fil stjerners pekere. Men det viser seg at det er et annet sett av funksjoner du kan bruke med å lese filer eller lesing fra nettverkstilkoblinger. Som en web server web lesertilkobling som faktisk bare bruker heltall i stedet pekere, som vi så på P satt fire. Men det er den samme ideen. Og jeg har gjort disse global å holde styr på en klient fil descriptor. Som en peker til hjemmesiden min klient. Og en server fil descriptor. Sortering av en peker til webserveren, men de er faktisk ikke pekere, de er bare tall. Til slutt har vi denne globale variabel her kalt signalisert. Som er min måte, sant eller usant, for å holde rede på hvorvidt brukeren har signalisert at han eller hun ønsker å stoppe webserveren. Og ja, det er en funksjon som lytter for kontroll C. Slik at hvis du som bruker, vil drepe serveren ved å trykke Kontroll C, at boolsk variabel du vil se i koden er satt til true. Og deretter innen en sløyfe holder vi å kontrollere verdien av denne variabel. Og hvis det er sant, vi bare avslutte programmet helt. La oss nå ta en titt på hoved. Du trenger ikke å forstå alt i hoved, men la oss gi deg en følelse av den totale arbeidsflyten. Og deretter ta en nærmere titt deg selv på noen av kommentarene. For det første, frem gjennom hoved, vi analysere kommandolinjeargumentene. Det viser seg at hoved er skal forvente enten dash h om hjelp, som bare forteller deg hvordan å kjøre programmet veldig konsist. Eller dash p, som lar du angir en port. Men igjen, ved hjelp av port 80 80, som standard, er hva du bør bruke CS 50 IDE. Neste, vi bare gjøre noen feilsjekking. Å sørge for at den portverdien er faktisk som vi forventer, innenfor et bestemt område. Og så litt av magien begynner. Vi kaller denne funksjonen starte, som vi skrev. Vi passerer inn med port, som samt eventuelle valgfrie argumenter for å starte serveren. Nærmere bestemt, at portnummer. Greit, neste, er dette ganske kryptisk kode som du ikke vil se for ofte, men det er en fancy måte å fortelle programmet til å lytte etter et signal. Et signal å være noe som en spesiell tastetrykk, som kontroll C. Så denne koden her er hvordan vi registrerer det som kalles en hendelse lytteren. Hvor og når som helst brukeren treffer Kontroll C denne koden forteller datamaskinen å kjøre en funksjon som heter handler. Som er skrevet lavere ned, implementert senke ned i denne filen, server.c, som stopper programmet helt. Men ingen grunn til å bekymre de indre detaljene der. La oss nå fokusere på den indre løkken. Ja, hva webserveren gjør er bevisst looping uendelig. Fordi etter alt det er ganske mye hva du vil ha en web server til å gjøre. Inntil du eksplisitt stoppe det, du bare ønsker å bli sittende der effektivt i en løkke, venter på noen på Internett for å koble til det. Slik at webserveren kan deretter svare på noen forespørsel. Legg merke til nå på toppen av programmet I fri noen variabler, fordi senere vil du ser vi bruker malloc noen steder. Så jeg vil bare gjøre at alle mine variabler er initialisert til noen kjente verdier. Ned her jeg sjekke om Programmet har blitt signalisert. Med andre ord, hvis brukeren treffer kontroll C, la oss bare slutte med denne sløyfen ved å ringe stopp. Og så nå denne koden blir litt mer interessant. Men legg merke til at du ikke har å skrive noe i main. Snarere innsiden av hoved Vi gjør følgende. Hvis brukeren har connected-- Dette er en funksjon vi skrev som returnerer sant eller usant. Og hver gang det heter det bare sier, ja, en klient, en browser har koblet til serveren. Eller, nei, det har ikke det. Og på denne måten kan vi bare sløyfe uendelig venter på ekte som skal returneres av den funksjonen. I mellomtiden, dette neste funksjon, forespørsel, vi også skrev for deg. Dette tar det som er inni som virtuell konvolutt, den såkalte HTTP be om, og faktisk analyserer det så å si. Ser på det topp til bunn, venstre til høyre, og laster alle disse innledende linjer. Som get linje og noe annet under den, inn i en variabel som vi har kalt meldingen. For en HTTP-melding. Og vi har også lastet dens lengde i lengden. Nå er dette litt annerledes. Så la oss ta en rask titt på dette. Selv om du ikke gjør det må gjennomføre anmodningen, det er nyttig, kanskje, for å forstå hvordan det fungerer. Denne forespørselen funksjonen tilsynelatende tar i to argumenter, melding og lengde. Men merker at jeg har bestått i en Ampersand til både melding og lengde. Men hvis vi bla opp, hva er meldingen og lengde? Vel merker at meldingen og Lengden er deklarert inne av hoved å være en char stjerne. Og en størrelse t. Som egentlig bare en int, henholdsvis. Så hva er nysgjerrig her, skjønt, er at hvis meldingen er en char stjerne men jeg har bestått i tegnet av melding, som er typen som tech får adressen til en peker. En dobbel pekeren, hvis du vil. Og faktisk, hvis jeg blar nedover. Helt ned i denne filen, der forespørselen er faktisk blir gjennomført, Jeg kommer til å se følgende signatur, eller prototype, for denne funksjonen. Som du har sikkert ikke sett før. Forespørselen funksjonen returnerer en bool. Det er sikkert kjent. Men legg merke til det første argumentet. Det kalles budskap, men jeg kunne ha kalt det noe her. Men det er røye star star. Og dette er en slags pene ting. Fordi jeg vil ha denne funksjonen be om å tildele minne for uansett hvor stor den HTTP-forespørsel er i den virtuelle konvolutt den mottar fra nettleseren, jeg ønsker å være i stand til å returnere en streng. Men jeg ønsker også å være i stand til å returnere en lengde. Så som du vil se i spesifikasjon, C, selvfølgelig, kan ikke returnere flere verdier. Og faktisk er jeg bare returnerer en bool her. Men akkurat som vi så i forelese en stund tilbake deg kan returnere to verdier hvis du passere i to verdier som referanse. Eller med pekeren. Slik at du faktisk kan gå til disse adressene, sette verdier der, og effektivt via denne tilbake kanal, så å si, kan en funksjon retur flere verdier til den som ringer. I dette tilfelle forespørselen kan returnere tre verdier. Dens faktiske returtype, en bool. Meldingen, en char star star. Og lengde, en størrelse t. Som er bare en int. Fordi denne funksjonen forespørsel kan gå til adressen lengde og sette en verdi der. Og det kan gå til adressen budskap og sette en verdi der. Og at nå bør være fornuftig. Fordi selv om meldingen er en char star, så snart du går det med stjerne melding, som vi har sett før i kode, hva har du tenkt å finne? Du kommer til å finne venter på du der, en del av minnet som bør være en char stjerne. Eller adressen til en streng. Og det er OK hvis du ikke helt wrap tankene rundt det for fort. Men tenk på at alt vi gjør tar adressen til en peker slik at vi kan gå dit og faktisk sette en peker der. Men ikke bekymre deg om det ikke helt synke akkurat nå. Vet for nå som forespørsel fungere effektivt gir deg disse tre verdier. Så la oss nå gå tilbake til hovedsiden. Hva som skjer neste, i Hoved, er følgende. Når jeg har fått innsiden av melding og lengde, de to verdiene jeg bryr meg om. Så går vi videre og skrive noen kode for deg som kan du lese bare den første linjen. Den såkalte forespørsel linje fra forespørselen. Nærmere bestemt, noe som get / HTTP 1.1, og ikke noe mer. Så det er en hel haug med andre HTTP-hoder, husker, at en nettleser sender fra en klient til en server. Vi bare ignorerer alle dem slik at alt du ser på terminalvinduet, husker, er bare noe lignende, get / hello.HTML HTP / 1.1. Så oppdager imidlertid at disse triks vi gjør her kommer til å være nyttig, kanskje, i ditt eget analysefunksjon som du vil gjennomføre. Legg merke til hvordan det er jeg bare erklære en variabel. Skjer for å være konst, som betyr, Jeg lover å ikke endre dette. Kalt høystakken. Så jeg cleverly oppkalt min neste variabel nål, slik at jeg kan proverbially se etter en nål i en høystakk, ved hjelp av en super hendig funksjon kalt str str. S-T-R-S-T-R, som i og for dens menneske side, eller per reference.CS50.NET, lar deg søke etter en streng i et annet. Og dette er min måte søker etter slutten av en linje slik at jeg kan faktisk lese bare en linje i minnet. Samtidig merker på linje 176 her, jeg faktisk allokere nok minne for den linjen. Og så bruker str og kopiere, og ved hjelp av bare en stråle brakett notasjon, lagrer jeg på at array? Akkurat som første linje. Faktisk, la meg bare hoppe over raskt spesifikasjonen for Oppgavesettet seks. Har lest gjennom dette i detalj. Men hva vil du finne er denne linjen her. Der basert på spesifikasjonen den formelle definisjonen HTTP vi spesifisere hva det aller første linjen skal være fra hvilken som helst nettleser til en server på innsiden av denne såkalt virtuell konvolutt. Spesielt bør leseren nevne en metode, som en bli, eller post, eller lignende. Så bokstavelig talt en plass, her representert med bare sp slik at det er eksplisitt at vi virkelig vil ha en plass her. Deretter be om målet som vil være noe sånt som /hello.HTML. Etterfulgt av en annen plass. Etterfulgt av en versjon. Som ville være noe sånt som HTTP / 1.1. Etterfulgt av C-R-L-F. Som er en akronym du kommer til å se mye i beskrivelsen. Og dette er bare en fancy måte sier backslash r, backslash n. Med andre ord, vogn tilbake, ny linje. Eller linjeskift. Linjeskift, linjeskift. Det er det C-R-L-F betyr. Nå, i mellomtiden, hvis vi gå tilbake til vår kode, la oss se hva som gjenstår for deg å gjøre. Innsiden av hoved, endelig, det er et kall til en parse funksjon. Formålet med parse er å ta det aller første linje, der definisjonen vi bare så på spesifikasjonen, og trekke den såkalte absolutt sti og spørring. Nå tar en titt på spec for hva vi mener med det. Men på lang historie kort, denne tingen her, forespørsel målet, er en streng som kan være delt opp i to deler. Eller en absolutt bane som /hello.HTML. Etterfulgt av en valgfri spørsmålstegn. Og så noe sånt q lik katter, eller q er lik hunder, eller en rekke nøkkelverdi parene som vi så i forelesning å være en del av parametriseringen av en HTTP-forespørsel. Så hva du kommer til å trenge å gjøre er å implementere parse. Og finne ut hvordan å iterere over linje, som er akkurat det første argumentet at vi kjører i. Karakter for karakter for karakter. Bare kommer opp til slutten av strengen. Leter du etter det absolutt sti og leter etter dette søket. Og hva er fint om det faktum at vi har gitt deg i dokumentasjonen denne grammatiske definisjonen av den første linje, her du nødt til å finne ut, vel, hva er metoden. Er gyldig eller ikke? Og vi fortelle deg på spec når det er eller ikke er gyldig. Få, for eksempel, vil være gyldig. Plass vil være lett å se etter. Bare ved hjelp av uke to stil eller problem satt to-stil streng kontroll. Eller tegn sjekke. Forespørsel målet er tingen du kommer til å ønske å analysere. Så ta en titt på spec for hva som er forventet der. Og så til slutt, HTTP versjon, du bare ønsker å sørge for at det er blant de støttede versjoner som HTTP 1.1. Så egentlig et parse funksjons kommer til å være en mulighet å bare lese denne tingen karakter for tegn for tegn, eller streng ved streng, noe som gjør at at det samsvarer med denne spesifikasjonen. Greit, tilbake til hoved. La oss se hva som gjenstår. Så antar du har nå implementert din parse funksjon. Vi har analysert ut fra det såkalte absolutte banen og spørringen, hva betyr viktigste nå har å gjøre med dette? Vel, en, vil du se i koden som vi URL dekodes i tilfelle nettleseren har kodede enkelte spesialtegn og spesiell måte, vi går fremover og konvertere dem tilbake til de aktuelle ASCII-tegn. Så går vi videre og finne ut om brukeren har bedt /hello.HTML, hva filen gjør de egentlig? Med andre ord, vi må ta roten av serveren, at banen til offentlig katalog, og sette sammen den med noe sånt, hello.HTML. Slik at vi har en større streng som fører oss nøyaktig til selve hello.HTML filen på CS50 IDE harddisk, eller disk. Deretter kontrollerer vi at sti finnes faktisk. Ellers vi kaster en 404-feil for brukeren. Og, faktisk hele vår kode du vil se en rekke anvendelser av denne feilen funksjon som vi selv skrev, og spesifikasjonen leder deg gjennom. Dette er bare en måte å returnere noe annet enn 200 til brukeren. Nå her nede, jeg går videre og finne ut er hva brukeren har bedt om en fil eller en katalog. For hvis det er en katalog, jeg ønsker å gjøre et par ting. En, hvis brukeren besøker et URL som er for en katalog, men slutter ikke i en skråstrek, for konvensjonelle grunner, Jeg vil være sikker på at vi endrer URL til faktisk ende i en skråstrek. Og så vil du se i kilde kode som vi har gitt deg, vi tvinge brukeren til å omdirigere til ikke [? fu?], men [? fu /,?] hvis de har gjort at. Og se spesifikasjonen tilsvarende. I mellomtiden sjekker vi en annen ting. Hvis brukeren har besøkt en katalog og den katalogen inneholder en fil som heter index.html eller index.php, menneskelig konvensjonen vi ønsker ikke å vise dem innholdet i denne katalogen. Vi ønsker å vise dem innholdet av at standardfilen, index.html, eller index.php. Og så koden jeg har uthevet her samtaler en funksjon kalt indekser som bare sjekker, eksisterer det en fil i her heter index.html eller index.php. Ellers, hvis ingen av disse vilkår gjelder vi bare kaller funksjonen liste, som vi skrev, som bokstavelig talt viser innholdet i en katalog. Greit, og hva om forespørselen at brukerens nettleser har gjort er ikke for en katalog, men for en fil? Vel, først vi kaller et oppslag funksjon. Som kommer til å fortelle server, er dette et JPEG, er dette en HTML-fil, er dette en GIF, eller et annet format. Hvis ja, er det da kommer til å sjekk, vel, det er en PHP-fil. I så fall ønsker vi å kalle en funksjon heter tolker, som vi skrev, som tolker at PHP fil og spytter ut resultatene. Eller, mer overbevisende, hvis det er noe annet, la oss gå videre og bare overføre filen. I likhet med GIF eller JPEG fra serveren til brukeren, som om de ba om en HTML-side, bilde, eller en rekke andre ting. Til slutt, hvis ingenting annet ser ut til å arbeid, vi bare kommer til å si 501. Som er at 501, ikke implementert melding, noe som betyr at serveren er ennå ikke fullført.