COLUMNA: Agora imos de mergullo no código de distribución e ter un ollar para o contexto en que o código que escribe estará en funcionamento. Ao final do día, está indo a aplicar a totalidade do servidor web. Pero nós fornecen Lo co esqueleto código que ten algunhas funcións, particularmente relacionadas coa rede. Imos dar un ollo. Entón, aquí enriba cara arriba do ficheiro é unha banda de recurso de proba requisitos macro. Agora, esta é só unha característica c, segundo o cal segundo unha morea de páxinas man tes que definir algúns dos esas constantes para ser verdade ou ser incluso números específicos, para que ten acceso a determinadas funcións. Se non, eles serán non declarado e non terá acceso. Entón eu fixen iso por medio ler as páxinas do manual. Agora alí en baixo, na liñas 15 a 17, nos ten unha morea de límites declarados. E nós temos prestado estes a partir dun servidor web popular chamado Apache. E estes son só números que van para limitar o número total de bytes que se permiten en varios contextos para a solicitude HTTP que un navegador se admite para me enviar. Logo definimos octetos. Agora, un octeto é só un xeito elegante de dicir un byte, ou oito bits. Acontece que no pasado un byte non era necesariamente oito bits, así octeto é sempre oito bits. Polo tanto, neste caso adoptado o que é común na rede mundo de chamar oito bytes un octeto. Aquí eu especifiquei que vai octetos ser 512, de xeito que moi parecido en medicina forense cando lemos unha morea de bytes de cada vez, tamén aquí, imos ler un banda de octetos de cada vez. Axiña unha morea de arquivos de cabeceira. Como eu sabía para incluír estes? Ben, eu simplemente ler o home páxinas a un número de funcións que imos usar neste distribución código e inclúen aqueles en Fun instruído a. E agora temos un tipo de datos. Temos declarou un octeto de ser un char. E nós veremos máis tarde que iso é utilizado ao longo do código. E nós temos declarado todo grupo de prototipos, e imos camiñar rapidamente a través cada unha destas funcións. Por último, e quizais o máis importante ter en mente neste momento no a historia, é que non son, en realidade, un conxunto grupo de variables globais na parte superior do ficheiro, raíz, CFD, SFD, solicitude, arquivo e corpo. Agora, xeralmente, utilizando tantos mundial variables ou variables globais en todo, Non é a práctica de volta. Pero acontece tamén estamos usando un técnica chamada de manipulación de sinal máis tarde no código, o que nos permite detectar cando o usuario chega algo como CTRL C e desactivar o servidor graciosamente. E, para facelo correctamente e, en realidade, liberar memoria, necesitamos ter acceso a estas variables globais. E agora imos dar un ollo ao principal, que impulsa a totalidade deste programa. En primeiro lugar, no alto aquí ter un número variable de erro que parece non ter un tipo, pero iso é porque é realmente definida nun ficheiro chamado erro errno.h que está incluído máis arriba. Se fai o home errno para realmente ver a definición de tal cousa, vai ver que este é un variable global especial que defínese por un grupo enteiro de funcións non escrita por nós, pero polos autores do Linux e outros sistemas para realmente definir un número para esa variable cando algo sae mal, para que poida globalmente descubrir o que deu errado. Agora, debaixo verá unha nova técnica quizais usando getopt, unha función que axuda mando parse Argumentos da liña de xeito que non facer ten que preocuparse en perder tempo imaxinando como analizar algo como 8080, ou trazo p, ou trazo h para obter axuda. getopt esencialmente fai iso por nós. Consulte a páxina de manual para máis. A continuación, facer un pouco de erro verificación para asegurarse de que o número de porto está dentro o intervalo especificado no spec. Logo vemos unha chamada á función comezar, cuxa definición imos mirar nun momento, e como o seu nome suxire, este inicia o servidor web. Aquí temos unha chamada a unha función chamado de sinal que di: se e cando escoitar Control C do teclado do usuario, dalle chamar un manipulador función chamada que está pasando cousas para, finalmente, limpar e deixar o servidor. Abaixo que é o que parece ser un ciclo infinito, a primeira liña das cales efectivamente é unha chamada a unha función chamada axustar, que nós mesmos aplicar, máis tarde, a fin para liberar algúns dos nosos estados globais. Despois que é unha liña de código que condicional está comprobando o retorno valor do contacto. Agora looks conectados como un predicado, algo que retorna verdadeiro ou falso. E fai, pero non hai algo especial en conectado na medida en que é unha chamada de bloqueo. Vai sentir alí e esperar ata que o navegador do usuario tenta conectarse a este web servidor e só entón el volver verdadeiro ou falso, para que poidamos continuar cara ao interior deste if. Unha vez alí, observe esta función a un función chamada de análise, o que escribimos, que analiza todo octetos, todo dos bytes procedentes dun navegador ao servidor, para que poidamos entregar Lo de volta, en definitiva o valor para outro desas variables globais que tendas de todo bytes en só cabeceiras de que solicitude, non o corpo se non houbese un corpo realmente a el. Agora baixo comezamos a analizar estes cabezallos para extraer un subconxunto da información que nos preocupa. En concreto, o per especificación, primeiro quería pedir liña, que é só que moito primeira liña que espero que di algo así como get cortar ou algún camiño e, a continuación, HTTP 1.1. Estamos a usar esa metáfora dunha agulla nun palheiro buscar especial caracteres ou enderezos. E, de feito, hai un número de funcións no noso código de distribución que, ademais, poden ser útiles cando se mira para valores particulares. En definitiva, nós copiar estes bytes nunha liña variable chamada, que notar, tamén, temos alocados na pila por medio dunha matriz Deseñada de forma dinámica. E nós estamos tentando deliberadamente para evitar chamar malloc porque de novo, porque Control de C sendo unha característica potencial deste programa, non quero ter ese código de súpeto interrompida polo bater do usuario Control C, o resultado dos cales é que eu non podería ter unha oportunidade de balde algo que malloced. Entón eu estou tentando utilizar a mesma cantidade da pila é que podo aquí. A continuación, un grupo enteiro de para dos. A especificación pode expoñer o que se espera aquí, pero os comentarios danlle unha información do que está por vir. Vostede primeiro que validar a liña de solicitude e asegúrese de que el se parece o especificacións gramática, por así dicir, di que debería. Logo cómpre extraer algo chamado a consulta, o material para fóra tras un signo de interrogación, como vimos co noso exemplo Google de paso nun parámetro de HD. Nós entón concatenar xuntos a raíz do servidor web co camiño que está que a primeira liña de solicitude e formar a ruta completa o ficheiro que quere buscar. Despois diso, imos estar seguro se o ficheiro existe e é lexible. E entón nós estamos indo a extraer o seu extensión de arquivo, o .html ou o .PHP, ou algunha extensión que está no final da cadea solicitado. Logo é un todo chea de código que escribimos para xerar efecto PHP contido xerado por ti. En poucas palabras, este código leva o nome do ficheiro que desexa PHP para interpretar. Nós pasalo por algo chamado un tubo en intérprete de PHP. Volva resposta como se a resposta fose ela mesma un arquivo. E, entón, interactuar sobre o ficheiro de bytes, tirando-los todos nun buffer para que poidamos, en última instancia imprimir-las. Efectivamente, todos estes chama aquí a dprintf nos permite imprimir algo chamado un descritor de ficheiro, o que é só un número enteiro que representa un ficheiro. Moi semellante en espírito, pero fundamentalmente diferente dun ficheiro punteiro estrela. Observe como pode usar a sintaxe como printf aquí para que eu poida dinamicamente inserir algo como a lonxitude ao valor dun cabeceira HTTP chamado Content-Length. E, finalmente, eu usei o dereito de realmente escribir función o corpo da solicitude. Desafortunadamente, só aplicado soporte para dinamicamente arquivos PHP xerada. Non aplicar o soporte para arquivos estáticos, como gifs, e JPEG e arquivos CSS e HTML. Isto, por desgraza, é deixarse ​​para ti para responder ao obxectivo cliente esta a facer. Entón, alí vai descubrir que non hai non moita inspiración dentro dese bloque, pero se un pouco máis arriba coa forma como nós fomos sobre a interpretación do código PHP, as funcións que vai empregar son un pouco diferentes. De feito, pode pedir algunhas das características quizais a partir dos forense conxunto de problemas, porque ao final do día todo o que necesitas facer aquí é cando vostede sabe que abrir o ficheiro e unha vez que sabe que se chama Tipo MIME ou tipo de contido, ten que ler neses bytes e dalgunha forma cuspi-los de volta para fóra. E agora un tour por esta outras funcións do arquivo. Ata primeiro está conectado, que simplemente retorna true cando finalmente escoita un conexión desde un usuario. Logo é erro. Erro, á súa vez, como unha función que escribiu para tratar con todas as diferentes 400 eo estado de HTTP 500 códigos que pode querer para enviar de volta para o usuario, xunto cunha mensaxe estándar. A continuación é a carga, especialmente función de carne, cuxo propósito na vida é para ler dunha estrela do punteiro do ficheiro do contido dun ficheiro nun buffer mundial que declarou a nivel mundial arriba [? principal. ?] Este é un pouco complexo, porque nós ten que ler os bytes do ficheiro pero comprobar en cada iteración se nós xa alcanzou o fin do ficheiro ou outra cousa deu mal. E usamos realloc para asegurarse de que calquera que sexa tapón Utilizamos está crecendo e crecendo e crecendo e sempre quedando á fronte do número de bytes que necesitamos para caber dentro. Handler, con todo, é a función que recibe chamado por medio de ter Control C rexistrado como un sinal que queremos interceptar. Observe aquí no manipulador que, en definitiva chamadas de parar, o que naturalmente para o servidor web. E, por desgraza, lookup non está implementado. En espírito, este é un función moi sinxelo. Dada a extensión do ficheiro, el que devolve-lo está o chamado MIME tipo ou tipo de contido. E nós especificar na especificación o que este cartografía debe ser. Pero ten que traducir en definitiva, ao código c. A continuación é a nosa función semellante de carne chamado de análise, cuxo propósito na vida é ler, non a partir dun ficheiro, pero desde unha conexión de rede. En concreto, a lectura e análise Solicitude HTTP que está vindo dun navegador ao servidor de xeito que en definitiva, podemos analizar con só as cabeceiras na solicitude liña e volver aqueles para ti por medio dunha memoria temporal global que declaramos riba [? principal. ?] Reset, con todo, é un función que definimos que se chama de forma iterativa dentro do principal cada vez que está a piques listo para comezar a escoitar para unha nova conexión de xeito que sempre sabemos o estado das nosas variables e para que nós tamén liberou calquera memoria que pode ser asignado para unha conexión de rede anterior. Axiña iníciase, o función que escribimos que contén un conxunto chea de código de rede que finalmente inicia o servidor web. Última up é a función chamado stop, que fai exactamente iso, para o servidor web. Pero, primeiro, el libera calquera memoria que aínda se asignado. Pero, en definitiva chama exit sen tan sequera voltar o control a nosa función principal. En definitiva, un dos a maioría das técnicas importantes ao aplicar este servidor web é vai ser un pouco de intento e erro, ter un navegador xanela aberta á dereita e unha fiestra de terminal en á esquerda, a consola de servidores fiestra, de xeito que pode ver as mensaxes que son sendo presentada na pantalla. Pero mellor aínda sería un terceiro fiestra, unha fiestra segundo terminal, en que usa o Telnet, o uso para o cal está prescrito no spec. E Telnet é só un moi programa de rede sinxelo que permite que finxir ser un navegador dunha fiestra mentres conversaba coa outra xanela. Desta forma, podes ver exactamente as ordes textuais que están volvendo do servidor ao cliente sen ter de desentullo en torno a creador de Chrome ferramentas en outra forma Interface clunkier.