ALTAVOZ: Ahora vamos a bucear en el código de distribución y echar un vistazo en el contexto en el que el código que escribir que se va a operar. Al final del día, usted va a poner en práctica la totalidad del servidor web. Pero hemos proporcionado que con el esqueleto código que tiene algunas funciones, particularmente en relación con la creación de redes. Vamos a echar un vistazo. Así que aquí hacia la parte superior del fichero es un manojo de la función de probar los requisitos de macro. Ahora bien, esto es sólo una característica de c, según el cual de acuerdo con un montón de páginas de manual usted tiene que definir algunas de estas constantes para ser verdad o ser incluso números específicos de manera que usted tiene acceso a ciertas funciones. De lo contrario van a ser no declarada y usted no tendrá acceso. Así que he hecho esto por medio de la lectura de las páginas de manual. Ahora abajo, en las líneas 15 y 17, que tienen un montón de límites declarados. Y hemos prestado estos de una servidor web popular llamado Apache. Y estos son sólo números que se va para limitar el número total de bytes que se permite en los diversos contextos de la petición HTTP que se permite a un navegador de enviarme. A continuación, definimos octetos. Ahora un octeto es sólo una forma elegante de decir un byte, u ocho bits. Resulta que en antaño un byte no era necesariamente ocho bits de modo octeto es siempre ocho bits. Así que en este caso hemos adoptado lo que es común en la red mundo de llamar a ocho bytes de un octeto. Aquí he especificado que octetos voluntad ser de 512, por lo que al igual que en el análisis forense cuando leemos un montón de bytes a la vez, también en este caso, vamos a leer un manojo de octetos a la vez. Siguiente un montón de archivos de cabecera. ¿Cómo sé que incluya estos? Bueno, yo simplemente leí el hombre páginas para un número de funciones que vamos a utilizar en esta distribución código e incluir en los Me dio instrucciones para. Y ahora tenemos un tipo de datos. Hemos declarado un octeto para ser un char. Y veremos más adelante que eso es utilizado en todo el código. Y hemos declarado una manojo entero de prototipos, y vamos a caminar rápidamente por cada una de esas funciones. Por último, y quizás lo más importante tener en la mente en este momento de la historia, es que no son, de hecho su conjunto montón de variables globales en la parte superior del archivo, raíz, CFD, SFD, solicitud, archivo y el cuerpo. Ahora generalmente, utilizando tantos mundial variables o variables globales en absoluto, no es la práctica de nuevo. Pero resulta que también estamos utilizando un técnica llamada manejo de señales más tarde en el código, lo que nos permite detectar cuando el usuario pulsa algo como CTRL C y se cerrará el servidor con gracia. Y con el fin de hacer eso con gracia y en realidad liberar memoria, necesitamos tener acceso a estas variables globales. Y ahora vamos a echar un vistazo a principal, que impulsa la totalidad de este programa. En primer lugar, en la parte superior aquí tener una variable de número de error que parece no tener un tipo, pero eso es porque en realidad definido en un archivo llamado errno.h error que se incluye más arriba. Si lo hace el hombre errno a realidad véase la definición de esta cosa, verás que se trata de un variable global especial que es fijado por un manojo entero de funciones no escrita por nosotros, sino por los autores de Linux y otros sistemas para establecer realmente un número a esa variable cuando algo va mal, para que pueda a nivel mundial averiguar lo que salió mal. Ahora abajo verás una nueva técnica tal vez usando getopt, una función que ayuda comando de análisis sintáctico argumentos de la línea para que no nos hacemos tiene que preocuparse de perder el tiempo pensando la manera de analizar algo así como 8080, o un guión p, o un guión h para obtener ayuda. getopt básicamente hace que para nosotros. Consulte la página de manual para más. A continuación, hacemos un poco de error comprobación para asegurarse de que el número de puerto está dentro del rango especificado en la especificación. A continuación, vemos una llamada a la función iniciar, cuya definición nos va mira en un momento, y como su nombre sugiere, este inicia el servidor web. Aquí tenemos una llamada a una función llama señal que dice: siempre y cuando escuche Control C de teclado del usuario, siga adelante y llame un controlador de función llamada que está pasando lo que en última instancia, limpias y dejar de el servidor. Debajo de eso es lo que parece ser un bucle infinito, la primera línea de los cuales efectivamente es una llamada a una función llamada restablecer, que nosotros mismos aplicar más adelante con el fin para liberar a algunos de nuestros estados globales. Después de que es una línea de código que condicionalmente está comprobando el retorno valor de conectado. Miradas Ahora conectados como un predicado, algo que devuelve verdadero o falso. Y lo hace, pero hay algo especial en conectado en que se trata de una llamada de bloqueo. Será sentarse allí y esperar hasta que el navegador del usuario intenta conectarse a esta web servidor y sólo entonces será return true o false para que procedamos en el interior de esta sentencia if. Una vez allí, observe esta función a un función llamada de análisis, lo que escribimos, que analiza todos los octetos, todo de los bytes procedentes de un navegador para el servidor, por lo que podemos entregar de vuelta en última instancia, un valor a uno de esas variables globales que almacena todos los bytes en sólo las cabeceras de ese solicitud, no el cuerpo si no eran en realidad un cuerpo a la misma. Ahora abajo comenzamos a analizar los encabezados para extraer un subconjunto de la información que nos preocupamos. Específicamente, por la especificación, nosotros primero quería pedir línea, que es sólo que muy primera línea que esperemos que dice algo así como get reducir o algún camino y luego HTTP 1.1. Estamos utilizando esta metáfora de una aguja en un pajar buscar en particular caracteres o direcciones. Y de hecho, hay un número de funciones en nuestro código de distribución que usted, también, puede ser que encuentre útil en la búsqueda de valores particulares. En última instancia, copiamos estos bytes en una línea de variable llamada, que notamos, también, tenemos asignado en la pila por medio de una matriz de tamaño dinámico. Y estamos tratando deliberadamente para evitar llamar a malloc porque, de nuevo, porque de Control C siendo una posible opción de este programa, no quiero tener este código de repente interrumpido por los golpes de usuario Control C, el resultado de los cuales es que yo no podría tener una oportunidad para algo gratis que he malloced. Así que estoy tratando de usar tanto de la pila es lo que pueda aquí. El siguiente, un montón de a dos. La especificación expondrá exactamente lo que se espera aquí, pero los comentarios que dan una pista de lo que está por venir. Primero tiene que validar la línea de petición y asegúrese de que parece que el especificaciones gramática, por así decirlo, dice que debería. A continuación, deberá extraer algo llamado la consulta, la materia hacia fuera después de un signo de interrogación, como vimos con nuestro ejemplo Google de pasada en un parámetro HD. Luego se concatena juntos la raíz del servidor web con la ruta que está en esa primera línea de petición y formar la ruta completa el archivo que queremos buscar. Después de eso, vamos a asegurarnos que el archivo existe y es legible. Y luego vamos a extraer su extensión de archivo, los archivos .html o .php la, o alguna extensión que está en el final de la cadena solicitada. El siguiente es un todo montón de código que escribimos para generar realmente PHP contenido para usted generado. En pocas palabras, esta código toma en el nombre del archivo que desea PHP interpretar. Nosotros pasamos por algo llamado un tubo en el intérprete de PHP. Vuelve la respuesta como si la respuesta fuera un archivo en sí mismo. Y luego iteramos sobre ese archivo de bytes, tirando todos en un búfer por lo que podemos en última instancia imprimirlos. De hecho, todos estos pide aquí para dprintf nos permite imprimir algo llamado un descriptor de archivo, que es simplemente un entero que representa un archivo. Muy similar en espíritu, pero fundamentalmente diferente de un archivo indicador de la estrella. Observe cómo se puede utilizar la sintaxis como printf aquí para que yo pueda dinámicamente insertar algo así como la longitud por el valor de una cabecera HTTP llamado Content-Length. Y en última instancia, he utilizado la función derecho a escribir en realidad el cuerpo de la solicitud. Por desgracia, sólo implementamos soporte para dinámicamente archivos PHP generados. No nos implementamos apoyo a archivos estáticos como gifs y archivos JPEG, y archivos CSS y HTML. Eso, por desgracia, se deja a usted para responder a la finalidad cliente esto que ver. Así que allí usted encontrará que hay no mucho inspiración dentro de ese bloque, pero si un poco más arriba de lo nos fuimos sobre la interpretación de código PHP, las funciones que se van a usar son un poco diferentes. De hecho, usted puede pedir prestado parte de la funcionalidad tal vez de la medicina forense conjunto de problemas, porque al final del día todo lo que necesita hacer aquí es una vez que sabes lo que abrir el archivo y una vez que usted sabe que el llamado Tipo MIME o tipo de contenido, usted necesita leer en esos bytes y de alguna manera ellos escupir de vuelta. Y ahora un recorrido por este otras funciones de archivo. Hasta se conecta primero, que simplemente devuelve true cuando por fin se oye un la conexión de un usuario. El siguiente es el error. Error, por su parte, como una función que escribió para manejar todas las diferentes 400 y el estado HTTP 500 códigos que usted puede ser que desee para enviar de nuevo al usuario, junto con un mensaje estándar. El siguiente paso es la carga, un particular función carnoso, cuyo propósito en la vida está a leer de una estrella archivo puntero del contenido de un archivo en una memoria intermedia mundial que declaramos a nivel mundial por encima de [? principal. ?] Esto es un poco compleja porque hay que leer los bytes del archivo pero comprobar en cada iteración si ya hemos golpear el final del archivo o algo ha ido mal. Y utilizamos realloc para asegurarse de que cualquier búfer que estamos usando es cada vez mayor y creciendo y creciendo y siempre mantenerse a la vanguardia de la cantidad de bytes que tenemos que encajar allí. Handler, por su parte, es la función que recibe llamado por manera de tener Control C registrada como una señal de que queremos interceptar. Nótese aquí en handler que en última instancia llamadas detienen, que por supuesto detiene el servidor web. Y, por desgracia, de búsqueda no se ha implementado. En espíritu, este es un función bastante simple. Dada la extensión de archivo, necesita para volver está el llamado MIME tipo o tipo de contenido. Y se especifica en el pliego de condiciones lo que la cartografía debe ser. Pero hay que traducir que en última instancia al código c. El siguiente es nuestra función similar a carne denominado parse, cuyo propósito en la vida es leer, no desde un archivo, pero a partir de una conexión de red. En concreto, la lectura y análisis de la Petición HTTP que ha llegado desde un navegador al servidor para que en última instancia, podemos analizar a tan sólo los encabezados de la solicitud línea y volver a aquellos que por medio de un tampón global que declaramos anteriormente [? principal. ?] Cambiar, por su parte, es un función que definimos que es llamada de forma iterativa el interior de principal cada vez que estás a punto listo para empezar a escuchar para una nueva conexión de manera que siempre sabemos el estado de nuestras variables y por lo que hemos también liberado cualquier memoria que podría haber sido asignado para una conexión de red anterior. El siguiente paso es empezar, la función que escribimos que contiene un conjunto gran cantidad de código de red que en última instancia se inicia el servidor web. Dura hasta es la función llamado parada, que hace exactamente eso, detiene el servidor web. Pero primero que libera cualquier memoria que aún se ha asignado. Pero llama en última instancia de salida sin ni siquiera devolver el control a nuestra función principal. En última instancia, una de las la mayoría de las técnicas importantes en la aplicación de este servidor web es va a ser un poco de ensayo y error, tener un navegador ventana abierta a la derecha y una ventana de terminal en izquierda, la consola de servidores ventana, de modo que usted puede ver los mensajes que se encuentran que se muestra en la pantalla. Pero mejor aún sería tercera ventana, una segunda ventana de terminal, en el que se utiliza Telnet, el uso para los que se prescribe en la especificación. Y Telnet es sólo una muy programa de red simple que le permite a finges ser un navegador en una ventana mientras habla con la otra ventana. De esta manera usted puede ver exactamente los comandos textuales que están regresando del servidor al cliente sin tener que meter alrededor de desarrollador de Chrome herramientas en una por lo demás interfaz clunkier.