1 00:00:00,000 --> 00:00:09,647 2 00:00:09,647 --> 00:00:11,730 COLUNA: Agora vamos de mergulho no código de distribuição 3 00:00:11,730 --> 00:00:14,470 e ter um olhar para o contexto em que o código que você escreve 4 00:00:14,470 --> 00:00:15,780 vai estar em funcionamento. 5 00:00:15,780 --> 00:00:17,350 No final do dia, você está indo para implementar 6 00:00:17,350 --> 00:00:18,710 a totalidade do servidor web. 7 00:00:18,710 --> 00:00:20,460 Mas nós fornecemos -lo com o esqueleto 8 00:00:20,460 --> 00:00:24,090 código que tem algumas funcionalidades, particularmente relacionadas com a rede. 9 00:00:24,090 --> 00:00:25,390 Vamos dar uma olhada. 10 00:00:25,390 --> 00:00:27,560 >> Então, aqui em cima em direção ao topo do arquivo é um bando 11 00:00:27,560 --> 00:00:30,020 de recurso de teste requisitos macro. 12 00:00:30,020 --> 00:00:33,570 Agora, esta é apenas uma característica de c, segundo o qual de acordo com um monte de páginas man 13 00:00:33,570 --> 00:00:36,410 você tem que definir alguns dos essas constantes para ser verdade 14 00:00:36,410 --> 00:00:39,920 ou ser até mesmo números específicos, para que você tem acesso a determinadas funções. 15 00:00:39,920 --> 00:00:42,470 Caso contrário, eles serão não declarado e você não terá acesso. 16 00:00:42,470 --> 00:00:45,340 Então eu fiz isso por meio de ler as páginas do manual. 17 00:00:45,340 --> 00:00:48,410 Agora lá em baixo, na linhas 15 a 17, nós 18 00:00:48,410 --> 00:00:50,550 tem um monte de limites declarados. 19 00:00:50,550 --> 00:00:53,370 >> E nós temos emprestado estes a partir de um servidor web popular chamado Apache. 20 00:00:53,370 --> 00:00:54,650 E estes são apenas números que vão 21 00:00:54,650 --> 00:00:56,810 para limitar o número total de bytes que são permitidos 22 00:00:56,810 --> 00:01:01,930 em vários contextos para a solicitação HTTP que um navegador é permitido para me enviar. 23 00:01:01,930 --> 00:01:04,310 Em seguida, definimos octetos. 24 00:01:04,310 --> 00:01:07,790 Agora, um octeto é apenas uma maneira elegante de dizer um byte, ou oito bits. 25 00:01:07,790 --> 00:01:10,720 Acontece que no passado um byte não era necessariamente oito bits, 26 00:01:10,720 --> 00:01:12,339 assim octeto é sempre oito bits. 27 00:01:12,339 --> 00:01:14,880 Portanto, neste caso adotamos o que é comum na rede 28 00:01:14,880 --> 00:01:17,410 mundo de chamar oito bytes um octeto. 29 00:01:17,410 --> 00:01:21,840 >> Aqui eu especifiquei que vai octetos ser 512, de modo que muito parecido em medicina forense 30 00:01:21,840 --> 00:01:24,170 quando lemos um monte de bytes de cada vez, também aqui, 31 00:01:24,170 --> 00:01:27,390 vamos ler um bando de octetos de cada vez. 32 00:01:27,390 --> 00:01:28,922 Em seguida um monte de arquivos de cabeçalho. 33 00:01:28,922 --> 00:01:30,255 Como eu sabia para incluir estes? 34 00:01:30,255 --> 00:01:32,730 Bem, eu simplesmente ler o homem páginas para um número de funções 35 00:01:32,730 --> 00:01:35,620 que vamos usar neste distribuição código e incluem aqueles em 36 00:01:35,620 --> 00:01:37,390 Fui instruído a. 37 00:01:37,390 --> 00:01:39,090 >> E agora nós temos um tipo de dados. 38 00:01:39,090 --> 00:01:41,470 Temos declarou um octeto de ser um char. 39 00:01:41,470 --> 00:01:44,040 E nós veremos mais tarde que isso é utilizado ao longo do código. 40 00:01:44,040 --> 00:01:45,670 E nós temos declarado todo grupo de protótipos, 41 00:01:45,670 --> 00:01:47,961 e vamos caminhar rapidamente através cada uma dessas funções. 42 00:01:47,961 --> 00:01:50,400 Por último, e talvez o mais importante ter em 43 00:01:50,400 --> 00:01:52,520 mente neste momento no a história, é que não 44 00:01:52,520 --> 00:01:54,520 são, na realidade, um conjunto grupo de variáveis ​​globais 45 00:01:54,520 --> 00:02:00,430 na parte superior do arquivo, raiz, CFD, SFD, pedido, arquivo e corpo. 46 00:02:00,430 --> 00:02:03,960 >> Agora, geralmente, utilizando tantos mundial variáveis ​​ou variáveis ​​globais em tudo, 47 00:02:03,960 --> 00:02:05,280 Não é a prática de volta. 48 00:02:05,280 --> 00:02:09,090 Mas acontece também estamos usando um técnica chamada de manipulação de sinal mais tarde 49 00:02:09,090 --> 00:02:11,930 no código, o que nos permite detectar quando o usuário atinge algo 50 00:02:11,930 --> 00:02:15,080 como CTRL C e desligar o servidor graciosamente. 51 00:02:15,080 --> 00:02:18,240 E, para fazer isso graciosamente e, na verdade, liberar memória, 52 00:02:18,240 --> 00:02:20,800 precisamos de ter acesso a essas variáveis ​​globais. 53 00:02:20,800 --> 00:02:24,510 >> E agora vamos dar uma olhada no principal, que impulsiona a totalidade deste programa. 54 00:02:24,510 --> 00:02:27,720 Em primeiro lugar, no topo aqui nós ter um número variável de erro 55 00:02:27,720 --> 00:02:29,570 que parece não ter um tipo, mas isso é 56 00:02:29,570 --> 00:02:31,500 porque é realmente definida em um arquivo chamado 57 00:02:31,500 --> 00:02:34,800 erro errno.h que está incluído mais acima. 58 00:02:34,800 --> 00:02:38,780 Se você fizer o homem errno para realmente ver a definição de tal coisa, 59 00:02:38,780 --> 00:02:41,230 você vai ver que este é um variável global especial que 60 00:02:41,230 --> 00:02:43,350 é definido por um grupo inteiro de funções não escrito 61 00:02:43,350 --> 00:02:48,730 por nós, mas pelos autores do Linux e outros sistemas para realmente definida 62 00:02:48,730 --> 00:02:52,400 um número para essa variável quando algo der errado, para que possa globalmente 63 00:02:52,400 --> 00:02:54,830 descobrir o que deu errado. 64 00:02:54,830 --> 00:02:58,540 >> Agora, logo abaixo você verá uma nova técnica talvez usando getopt, 65 00:02:58,540 --> 00:03:01,790 uma função que ajuda comando parse Argumentos da linha de modo que não fazer 66 00:03:01,790 --> 00:03:05,540 tem que se preocupar em perder tempo imaginando como analisar algo como 8080, 67 00:03:05,540 --> 00:03:08,350 ou traço p, ou traço h para obter ajuda. 68 00:03:08,350 --> 00:03:10,300 getopt essencialmente faz isso por nós. 69 00:03:10,300 --> 00:03:11,750 Veja a página de manual para mais. 70 00:03:11,750 --> 00:03:13,960 >> Em seguida, fazer um pouco de erro verificação para certificar-se 71 00:03:13,960 --> 00:03:17,420 que o número de porta está dentro o intervalo especificado no spec. 72 00:03:17,420 --> 00:03:20,240 Em seguida, vemos uma chamada para a função começar, cuja definição vamos 73 00:03:20,240 --> 00:03:24,040 olhar em um momento, e como o próprio nome sugere, este inicia o servidor web. 74 00:03:24,040 --> 00:03:26,960 Aqui nós temos uma chamada a uma função chamado de sinal que diz: 75 00:03:26,960 --> 00:03:30,750 se e quando você ouvir Controle C do teclado do usuário, vá em frente e chamar 76 00:03:30,750 --> 00:03:34,650 um manipulador função chamada que está acontecendo coisas para, finalmente, limpar e parar 77 00:03:34,650 --> 00:03:35,500 o servidor. 78 00:03:35,500 --> 00:03:39,470 >> Abaixo que é o que parece ser um ciclo infinito, a primeira linha das quais 79 00:03:39,470 --> 00:03:41,660 efetivamente é uma chamada a uma função chamada 80 00:03:41,660 --> 00:03:45,110 redefinir, que nós mesmos implementar, mais tarde, a fim 81 00:03:45,110 --> 00:03:47,470 para liberar alguns de nossos estados globais. 82 00:03:47,470 --> 00:03:50,480 Depois que é uma linha de código que condicionalmente 83 00:03:50,480 --> 00:03:52,576 está verificando o retorno valor do ligado. 84 00:03:52,576 --> 00:03:55,700 Agora looks conectados como um predicado, algo que retorna verdadeiro ou falso. 85 00:03:55,700 --> 00:03:58,040 E ele faz, mas não há algo especial em conectado 86 00:03:58,040 --> 00:03:59,960 na medida em que é uma chamada de bloqueio. 87 00:03:59,960 --> 00:04:03,180 Ele vai sentar lá e esperar até que o navegador do usuário 88 00:04:03,180 --> 00:04:05,860 tenta se conectar a este web servidor e só então ele 89 00:04:05,860 --> 00:04:10,160 retornar verdadeiro ou falso, para que possamos continuar para o interior deste if. 90 00:04:10,160 --> 00:04:13,870 >> Uma vez lá, observe esta função a um função chamada de análise, o que nós escrevemos, 91 00:04:13,870 --> 00:04:17,230 que analisa todos os octetos, todos dos bytes provenientes de um navegador 92 00:04:17,230 --> 00:04:21,010 para o servidor, para que possamos entregar -lo de volta, em última análise o valor para outro 93 00:04:21,010 --> 00:04:24,420 dessas variáveis ​​globais que lojas de todos os bytes em apenas 94 00:04:24,420 --> 00:04:26,630 os cabeçalhos de que pedido, não o corpo 95 00:04:26,630 --> 00:04:28,920 se não houvesse um corpo realmente a ele. 96 00:04:28,920 --> 00:04:32,980 >> Agora abaixo começamos a analisar estes cabeçalhos para extrair 97 00:04:32,980 --> 00:04:35,490 um subconjunto das informações que nos preocupamos. 98 00:04:35,490 --> 00:04:37,740 Especificamente, o per especificação, primeiro 99 00:04:37,740 --> 00:04:40,580 queria pedir linha, que é só que muito primeira linha que 100 00:04:40,580 --> 00:04:45,710 espero que diz algo como get cortar ou algum caminho e, em seguida, HTTP 1.1. 101 00:04:45,710 --> 00:04:48,150 Estamos usando essa metáfora de uma agulha num palheiro 102 00:04:48,150 --> 00:04:50,370 procurar especial caracteres ou endereços. 103 00:04:50,370 --> 00:04:53,120 E, de fato, há um número de funções em nosso código de distribuição 104 00:04:53,120 --> 00:04:56,930 que você, também, podem ser úteis quando se olha para valores particulares. 105 00:04:56,930 --> 00:05:00,630 >> Em última análise, nós copiar esses bytes em uma linha variável chamada, 106 00:05:00,630 --> 00:05:03,510 que notar, também, nós temos alocados na pilha 107 00:05:03,510 --> 00:05:05,890 por meio de uma matriz dimensionada de forma dinâmica. 108 00:05:05,890 --> 00:05:08,350 E nós estamos tentando deliberadamente para evitar chamar malloc 109 00:05:08,350 --> 00:05:11,100 porque de novo, porque Controlo de C sendo 110 00:05:11,100 --> 00:05:14,630 uma característica potencial deste programa, não quero ter esse código de repente 111 00:05:14,630 --> 00:05:17,479 interrompida pelo bater do usuário Controlo C, o resultado dos quais 112 00:05:17,479 --> 00:05:20,270 é que eu não poderia ter uma chance de graça algo que eu malloced. 113 00:05:20,270 --> 00:05:23,660 Então eu estou tentando usar a mesma quantidade da pilha é que eu posso aqui. 114 00:05:23,660 --> 00:05:26,040 >> Em seguida, um grupo inteiro de para dos. 115 00:05:26,040 --> 00:05:28,930 A especificação irá expor exatamente o que é esperado aqui, 116 00:05:28,930 --> 00:05:31,800 mas os comentários dão-lhe uma dica do que está por vir. 117 00:05:31,800 --> 00:05:33,830 Você primeiro precisa validar a linha de pedido 118 00:05:33,830 --> 00:05:37,760 e certifique-se que ele se parece com o especificações gramática, por assim dizer, 119 00:05:37,760 --> 00:05:38,541 diz que deveria. 120 00:05:38,541 --> 00:05:41,290 Em seguida, você precisa extrair algo chamado a consulta, o material para fora 121 00:05:41,290 --> 00:05:44,200 após um ponto de interrogação, como vimos com o nosso exemplo Google 122 00:05:44,200 --> 00:05:46,320 de passagem em um parâmetro de HD. 123 00:05:46,320 --> 00:05:49,050 Nós então concatenar juntos a raiz do servidor web 124 00:05:49,050 --> 00:05:52,520 com o caminho que está em que a primeira linha de pedido 125 00:05:52,520 --> 00:05:56,010 e formar o caminho completo o arquivo que deseja procurar. 126 00:05:56,010 --> 00:06:00,300 >> Depois disso, vamos ter a certeza se o arquivo existe e é legível. 127 00:06:00,300 --> 00:06:05,100 E então nós estamos indo para extrair o seu extensão de arquivo, o .html ou o .php, 128 00:06:05,100 --> 00:06:09,920 ou alguma extensão que está no final da cadeia solicitado. 129 00:06:09,920 --> 00:06:11,940 Em seguida é um todo monte de código que escrevemos 130 00:06:11,940 --> 00:06:15,800 para gerar efectivamente PHP conteúdo gerado por você. 131 00:06:15,800 --> 00:06:18,010 Em poucas palavras, este código leva no nome 132 00:06:18,010 --> 00:06:20,250 do arquivo que você deseja PHP para interpretar. 133 00:06:20,250 --> 00:06:24,630 Nós passá-lo por algo chamado um tubo em intérprete de PHP. 134 00:06:24,630 --> 00:06:28,060 Volte a resposta como se a resposta fosse ela própria um arquivo. 135 00:06:28,060 --> 00:06:32,110 E, então, interagir sobre esse arquivo de bytes, puxando-los todos em um buffer 136 00:06:32,110 --> 00:06:34,180 para que possamos, em última instância imprimi-las. 137 00:06:34,180 --> 00:06:37,230 >> Com efeito, todos estes chama aqui a dprintf 138 00:06:37,230 --> 00:06:40,110 nos permite imprimir algo chamado de um descritor de arquivo, o que 139 00:06:40,110 --> 00:06:42,350 é apenas um número inteiro que representa um arquivo. 140 00:06:42,350 --> 00:06:45,360 Muito semelhante em espírito, mas fundamentalmente diferente de um arquivo 141 00:06:45,360 --> 00:06:46,620 ponteiro estrela. 142 00:06:46,620 --> 00:06:50,260 Observe como você pode usar a sintaxe como printf aqui para que eu possa dinamicamente 143 00:06:50,260 --> 00:06:54,000 inserir algo como o comprimento para o valor de um cabeçalho HTTP 144 00:06:54,000 --> 00:06:55,270 chamado Content-Length. 145 00:06:55,270 --> 00:06:57,990 E, finalmente, eu usei o direito de realmente escrever função 146 00:06:57,990 --> 00:07:00,040 o corpo do pedido. 147 00:07:00,040 --> 00:07:03,750 >> Infelizmente, só implementado suporte para dinamicamente 148 00:07:03,750 --> 00:07:05,350 arquivos PHP gerada. 149 00:07:05,350 --> 00:07:08,520 Nós não implementar o suporte para arquivos estáticos, como gifs, e JPEG 150 00:07:08,520 --> 00:07:10,660 e arquivos CSS e HTML. 151 00:07:10,660 --> 00:07:14,450 Isso, infelizmente, é deixada para você para responder ao objectivo cliente 152 00:07:14,450 --> 00:07:15,090 esta a fazer. 153 00:07:15,090 --> 00:07:20,050 Então, lá você vai descobrir que não há não muita inspiração dentro desse bloco, 154 00:07:20,050 --> 00:07:23,520 mas se você um pouco mais para cima com a forma como nós fomos sobre a interpretação do código PHP, 155 00:07:23,520 --> 00:07:25,520 as funções que você vai usar são um pouco diferentes. 156 00:07:25,520 --> 00:07:27,561 >> Na verdade, você pode pedir algumas das funcionalidades 157 00:07:27,561 --> 00:07:29,620 talvez a partir dos forense conjunto de problemas, porque 158 00:07:29,620 --> 00:07:32,860 no fim do dia tudo o que precisa fazer aqui é quando você sabe que abrir o arquivo 159 00:07:32,860 --> 00:07:35,690 e uma vez que você sabe que é chamado Tipo MIME ou tipo de conteúdo, 160 00:07:35,690 --> 00:07:39,040 você precisa ler nesses bytes e de alguma forma cuspi-los de volta para fora. 161 00:07:39,040 --> 00:07:41,190 >> E agora um tour por esta outras funções do arquivo. 162 00:07:41,190 --> 00:07:43,820 Até primeiro está ligado, que simplesmente retorna true 163 00:07:43,820 --> 00:07:47,350 quando finalmente ouve um conexão a partir de um utilizador. 164 00:07:47,350 --> 00:07:48,786 Em seguida é erro. 165 00:07:48,786 --> 00:07:52,296 Erro, por sua vez, como uma função que escreveu para lidar com todas as diferentes 400 166 00:07:52,296 --> 00:07:55,360 eo status HTTP 500 códigos que você pode querer 167 00:07:55,360 --> 00:07:58,500 para enviar de volta para o usuário, juntamente com uma mensagem padrão. 168 00:07:58,500 --> 00:08:01,950 >> Em seguida é a carga, particularmente função de carne, cujo propósito na vida 169 00:08:01,950 --> 00:08:06,920 é para ler de uma estrela do ponteiro do arquivo do conteúdo de um arquivo em um buffer mundial 170 00:08:06,920 --> 00:08:09,000 que declarou a nível mundial acima [? principal. ?] 171 00:08:09,000 --> 00:08:12,649 Este é um pouco complexo, porque nós tem que ler os bytes do arquivo 172 00:08:12,649 --> 00:08:14,690 mas verificar em cada iteração se nós já 173 00:08:14,690 --> 00:08:17,600 atingiu o fim do ficheiro ou outra coisa deu errado. 174 00:08:17,600 --> 00:08:21,210 E usamos realloc para se certificar de que qualquer que seja tampão estamos usando está crescendo 175 00:08:21,210 --> 00:08:24,440 e crescendo e crescendo e sempre ficando à frente do número de bytes 176 00:08:24,440 --> 00:08:25,675 que precisamos para caber lá dentro. 177 00:08:25,675 --> 00:08:27,550 Handler, entretanto, é a função que recebe 178 00:08:27,550 --> 00:08:30,630 chamado por meio de ter Controlo C registado como um sinal 179 00:08:30,630 --> 00:08:32,140 que queremos interceptar. 180 00:08:32,140 --> 00:08:34,070 Observe aqui no manipulador que, em última análise 181 00:08:34,070 --> 00:08:36,780 chamadas de parar, o que naturalmente pára o servidor web. 182 00:08:36,780 --> 00:08:39,750 E, infelizmente, lookup não está implementado. 183 00:08:39,750 --> 00:08:41,940 Em espírito, este é um função bastante simples. 184 00:08:41,940 --> 00:08:44,900 Dada a extensão do arquivo, ele precisa devolvê-lo está o chamado MIME 185 00:08:44,900 --> 00:08:46,320 tipo ou tipo de conteúdo. 186 00:08:46,320 --> 00:08:49,260 E nós especificar na especificação o que esse mapeamento deve ser. 187 00:08:49,260 --> 00:08:52,330 Mas você precisa traduzir em última análise, ao código c. 188 00:08:52,330 --> 00:08:56,490 >> Em seguida é a nossa função semelhante de carne chamado de análise, cujo propósito na vida 189 00:08:56,490 --> 00:08:59,350 é ler, não a partir de um arquivo, mas a partir de uma conexão de rede. 190 00:08:59,350 --> 00:09:03,510 Especificamente, a leitura e a análise Pedido HTTP que está vindo de um navegador 191 00:09:03,510 --> 00:09:05,940 para o servidor de modo a que em última análise, podemos analisar 192 00:09:05,940 --> 00:09:09,530 com apenas os cabeçalhos no pedido linha e retornar aqueles para você 193 00:09:09,530 --> 00:09:12,720 por meio de uma memória temporária global que declaramos acima [? principal. ?] 194 00:09:12,720 --> 00:09:14,880 >> Reset, entretanto, é um função que nós definimos 195 00:09:14,880 --> 00:09:18,730 que é chamado de forma iterativa dentro do principal cada vez que você está prestes 196 00:09:18,730 --> 00:09:20,799 pronto para começar a ouvir para uma nova ligação 197 00:09:20,799 --> 00:09:22,840 de modo que nós sempre sabemos o estado de nossas variáveis 198 00:09:22,840 --> 00:09:24,870 e para que nós também libertou qualquer memória que 199 00:09:24,870 --> 00:09:28,070 pode ter sido alocado para uma conexão de rede anterior. 200 00:09:28,070 --> 00:09:30,060 Em seguida é iniciado, o função que escrevemos 201 00:09:30,060 --> 00:09:31,920 que contém um conjunto monte de código de rede 202 00:09:31,920 --> 00:09:34,420 que, finalmente, inicia o servidor web. 203 00:09:34,420 --> 00:09:36,680 >> Última up é a função chamado stop, que 204 00:09:36,680 --> 00:09:38,770 faz exatamente isso, pára o servidor web. 205 00:09:38,770 --> 00:09:42,270 Mas, primeiro, ele libera qualquer memória que ainda foi alocado. 206 00:09:42,270 --> 00:09:45,850 Mas, em última análise chama exit sem nem mesmo retornar o controle 207 00:09:45,850 --> 00:09:47,480 a nossa função principal. 208 00:09:47,480 --> 00:09:49,480 Em última análise, um dos a maioria das técnicas importantes 209 00:09:49,480 --> 00:09:52,680 ao implementar este servidor web é vai ser um pouco de tentativa e erro, 210 00:09:52,680 --> 00:09:55,886 ter um navegador janela aberta à direita e uma janela de terminal em 211 00:09:55,886 --> 00:09:57,760 à esquerda, o console de servidores janela, de modo que você 212 00:09:57,760 --> 00:10:00,420 pode ver as mensagens que são sendo apresentada no ecrã. 213 00:10:00,420 --> 00:10:04,170 >> Mas melhor ainda seria um terceiro janela, uma janela segundo terminal, 214 00:10:04,170 --> 00:10:07,135 em que você usar o Telnet, o uso para o qual está prescrito no spec. 215 00:10:07,135 --> 00:10:09,640 E Telnet é apenas um muito programa de rede simples 216 00:10:09,640 --> 00:10:12,660 que permite que você fingir ser um navegador de uma janela 217 00:10:12,660 --> 00:10:14,540 enquanto conversava com a outra janela. 218 00:10:14,540 --> 00:10:16,830 Desta forma, você pode ver exactamente os comandos textuais 219 00:10:16,830 --> 00:10:18,700 que estão voltando do servidor para o cliente 220 00:10:18,700 --> 00:10:20,810 sem ter de desentupimento em torno de desenvolvedor do Chrome 221 00:10:20,810 --> 00:10:24,010 ferramentas em uma outra forma Interface clunkier. 222 00:10:24,010 --> 00:10:29,099