La plongée de Maintenant, nous allons: ENCEINTE dans le code de distribution
et jeter un oeil sur le contexte dans lequel le code que vous écrivez
va fonctionner.
A la fin de la journée, vous allez mettre en œuvre
la totalité du serveur web.
Mais nous avons fourni vous avec le squelette
Code qui ont une certaine fonctionnalité, notamment liés à la mise en réseau.
Jetons un coup d'oeil.
>> Donc, ici vers le haut du fichier est un tas
des exigences de test de fonctionnalités macro.
Maintenant, ce est juste une fonction de c, lequel selon un tas de pages de manuel
vous devez définir certains des ces constantes pour être vrai
ou encore des numéros spécifiques de sorte que vous avez accès à certaines fonctions.
Sinon ils seront non déclarés et vous ne aurez pas accès.
Donc, je ai fait cela par de lire les pages de manuel.
Maintenant en bas, dans lignes 15 à 17, nous
avoir tout un tas de limites déclarées.
>> Et nous avons emprunté ce à partir d'un serveur Web populaire appelé Apache.
Et ce ne sont là chiffres qui vont
de plafonner le nombre total d'octets qui sont autorisés
dans divers contextes de la requête HTTP qu'un navigateur est autorisé à me envoyer.
Ensuite, nous définissons octets.
Maintenant un octet est juste une façon élégante de dire un octet, ou huit bits.
Il se avère que dans un octet antan ne était pas nécessairement huit bits
afin octet est toujours huit bits.
Donc, dans ce cas, nous avons adopté ce qui est commun dans le réseau
monde d'appeler huit octets un octet.
>> Ici, je ai précisé que octets sera être 512, de sorte que tout comme en médecine légale
quand nous lisons un tas de octets à la fois, ici aussi,
nous allons lire un tas d'octets à la fois.
Suivant tout un tas de fichiers d'en-tête.
Comment ai-je sais de les inclure?
Eh bien je ai simplement lu l'homme pages pour un certain nombre de fonctions
que nous allons utiliser dans cette distribution code et inclure dans ceux
Je ai été chargé de.
>> Et maintenant nous avons un type de données.
Nous avons déclaré un octet d'être un produit de carbonisation.
Et nous verrons plus tard que ce est utilisée dans le code.
Et nous avons déclaré un tas ensemble de prototypes,
et nous allons marcher rapidement à travers chacune de ces fonctions.
Enfin, et peut-être plus important de garder à
l'esprit à ce moment- l'histoire, ce est qu'il ya
sont en fait un ensemble tas de variables globales
au début du fichier, racine, CFD, SFD, demande, fichier et le corps.
>> Maintenant, en général, en utilisant tant mondial variables ou variables globales à tous,
ne est pas la pratique de retour.
Mais il se avère que nous sommes également en utilisant un technique appelée traitement du signal plus tard
dans le code, ce qui nous permet de détecter le moment où l'utilisateur appuie sur quelque chose
comme CTRL C et se arrêtera le serveur gracieusement.
Et pour le faire gracieusement et effectivement libérer de la mémoire,
nous avons besoin d'avoir accès à ces variables globales.
>> Et maintenant, nous allons jeter un oeil à principal, qui entraîne l'ensemble de ce programme.
Tout d'abord, en haut ici, nous avoir un nombre variable d'erreur
qui apparaît pas à avoir un type, mais ce est
parce que ce est fait définie dans un fichier appelé
erreur qui errno.h est inclus ci-dessus.
Si vous faites l'homme errno à fait voir la définition pour cette chose,
vous verrez que ce est un variable globale spéciale
est fixé par tout un tas des fonctions non écrite
par nous, mais par les auteurs de Linux et d'autres systèmes de réellement mis
un certain nombre à cette variable lorsque quelque chose qui ne va pas afin que vous puissiez l'échelle mondiale
comprendre ce qui fait aller mal.
>> Maintenant en bas vous verrez une nouvelle technique utilisant peut-être getopt,
une fonction qui permet de commande parse les arguments de ligne de telle sorte que nous ne avons pas
à se soucier de perdre du temps figurer comment analyser quelque chose comme 8080,
ou un tiret p, ou un tiret h pour obtenir de l'aide.
getopt fait essentiellement que pour nous.
Voir la page de manuel pour plus.
>> Ensuite, nous faisons un peu d'erreur vérification pour se assurer
que le numéro de port est dans la gamme spécifiée dans la spécification.
Ensuite, nous voyons un appel à la fonction commencer, dont la définition nous
regarder dans un moment, et comme son nom indique, il démarre le serveur Web.
Ici, nous avons un appel à une fonction appelé signal qui dit,
si et quand vous entendez le contrôle de C le clavier de l'utilisateur, allez-y et appelez
un gestionnaire de fonction appelée ce qui se passe choses à finalement propres et arrêter
le serveur.
>> Ci-dessous, ce est ce qui semble être un boucle infinie, la première ligne dont
est effectivement un appel à une fonction appelée
réinitialiser, qui nous-mêmes nous mettre en œuvre plus tard dans l'ordre
afin de libérer certains de nos états globaux.
Après ce est une ligne de code qui conditionnellement
est de vérifier le retour La valeur de connecté.
Maintenant regards connectés comme un prédicat, quelque chose qui renvoie true ou false.
Et il le fait, mais il est quelque chose de spécial dans connecté
en ce qu'il se agit d'un appel de blocage.
Il va rester là et attendre jusqu'à ce que le navigateur d'un utilisateur
tente de se connecter à ce site web serveur et alors seulement il
retourner true ou false afin que nous procédons à l'intérieur de cette instruction if.
>> Une fois là, vous remarquerez cette fonction à un fonction appelée parse, qui nous avons écrit,
qui analyse tous les octets, tous les des octets provenant d'un navigateur
sur le serveur, de sorte que nous pouvons remettre vous revenir finalement une valeur à une
de ces variables globales stocke tous les octets en seulement
les en-têtes de cette demande, pas le corps
se il y avait en fait un corps à elle.
>> Maintenant bas nous commençons à analyser ces en-têtes pour extraire
un sous-ensemble des informations que nous nous soucions.
Plus précisément, par le spécification, nous avons d'abord
voulu demander ligne, qui est juste que première ligne
dit quelque chose comme je l'espère get slash ou un chemin, puis 1,1 HTTP.
Nous utilisons cette métaphore d'une aiguille dans une botte de foin
à chercher notamment caractères ou des adresses.
Et en effet, il ya un certain nombre de fonctions dans notre code de distribution
que vous, aussi, pourraient trouver utile quand on regarde pour des valeurs particulières.
>> En fin de compte, nous copions ces octets en une ligne de variable appelée,
qui remarque aussi, nous avons alloué sur la pile
par l'intermédiaire d'une matrice de calibrage dynamique.
Et nous tente délibérément pour éviter d'appeler malloc
car encore une fois, parce Contrôle de C étant
une fonction potentiel de ce programme, nous ne voulez pas avoir ce code coup
interrompue par l'utilisateur frappe Contrôle de C, dont le résultat
ce est que je ne pourrais pas avoir une chance quelque chose de libre, je ai malloced.
Je essaie donc d'utiliser autant de la pile est que je peux ici.
>> Ensuite, tout un tas de à dos.
La spécification exposera exactement ce qu'on attend ici,
mais les commentaires vous donnent un soupçon de ce qui nous attend.
Vous devez d'abord valider la ligne de demande
et assurez-vous qu'il ressemble à la spécifications grammaire, pour ainsi dire,
dit il se doit.
Vous devez ensuite extraire quelque chose appelé la requête, l'étoffe
après un point d'interrogation, comme nous avons vu notre exemple Google
en passant dans un paramètre HD.
Nous concaténons puis ensemble la racine du serveur Web
avec le chemin qui est en cette demande première ligne
et former le chemin complet du le fichier que nous voulons rechercher.
>> Par la suite, nous allons faire en sorte que le fichier existe et est lisible.
Et puis nous allons extraire son extension de fichier, le .html ou .php,
ou une telle extension qui est au fin de la chaîne demandée.
Ensuite, il ya un tout tas de code que nous avons écrit
à générer réellement PHP contenu généré pour vous.
En un mot, cette Code prend au nom
du fichier que vous voulez interpréter PHP.
Nous passons par quelque chose appelé un tuyau dans l'interprète de PHP.
Retournez la réponse comme si la réponse était un fichier lui-même.
Et puis nous parcourons ce fichier de octets, tous tirant dans une mémoire tampon
afin que nous puissions finalement les imprimer.
>> En effet, l'ensemble de ceux-ci appelle ici pour dprintf
nous permet d'imprimer quelque chose appelé un descripteur de fichier, ce qui
est juste un nombre entier qui représente un fichier.
Très similaire dans l'esprit, mais fondamentalement différente d'un fichier
pointeur étoiles.
Remarquez comment vous pouvez utiliser la syntaxe comme printf ici pour que je puisse dynamiquement
insérer quelque chose comme la longueur pour la valeur d'un en-tête HTTP
appelé Content-Length.
Et, finalement, je ai utilisé le droit de réellement écrire fonction
le corps de la demande.
>> Malheureusement, nous ne avons mis en place soutien à dynamiquement
fichiers PHP générés.
Nous ne avons pas implémenter un support pour fichiers statiques comme les gifs, jpeg, et
et les fichiers CSS et HTML.
Que, malheureusement, est laissé à vous pour répondre à l'objet de client
ce qu'il faut faire.
Alors là, vous trouverez qu'il ya pas beaucoup d'inspiration au sein de ce bloc,
mais si vous un peu plus haut comment nous sommes allés sur l'interprétation du code PHP,
les fonctions que vous utiliserez sont un peu différent.
>> En fait, vous pouvez emprunter certaines des fonctionnalités
peut-être de la médecine légale jeu de problème, parce que
à la fin de la journée tout ce que vous devez faire ici est une fois que vous savez ce fichier ouvert
et une fois que vous savez qu'il est soi-disant Le type MIME ou le type de contenu,
vous devez lire dans ces octets et en quelque sorte de les recracher.
>> Et maintenant, une visite de cette autres fonctions de fichiers.
Jusqu'à la première est reliée, qui retourne simplement vrai
quand il entend enfin un connexion d'un utilisateur.
Ensuite, il ya erreur.
Erreur, quant à lui, en fonction nous écrit pour gérer l'ensemble de la différente 400
et l'état HTTP 500 codes que vous voudrez peut-
à renvoyer à l'utilisateur, avec un message standard.
>> Ensuite, il ya la charge, particulièrement fonction viande, dont le but dans la vie
est à lire d'une étoile de pointeur de fichier du contenu d'un fichier dans un tampon mondiale
que nous avons déclaré au niveau mondial ci-dessus [? principale. ?]
Ce est un peu complexe parce que nous avoir à lire les octets du fichier
mais il faut vérifier à chaque itération si nous avons déjà
frapper la fin du fichier ou autre chose se est mal passé.
Et nous utilisons realloc pour se assurer que quel que soit le tampon que nous utilisons est en croissance
et de plus en plus et de plus en plus et toujours rester en tête du nombre d'octets
que nous devons adapter là.
Handler, quant à lui, est la fonction qui obtient
appelé par voie d'avoir Contrôle C enregistré comme un signal
que nous voulons intercepter.
Remarquez ici dans le gestionnaire qu'il finalement
appels arrêtent, ce qui bien sûr arrête le serveur Web.
Et malheureusement, recherche ne est pas mis en œuvre.
Dans l'esprit, ce est un fonction assez simple.
Compte tenu de l'extension de fichier, il doit pour revenir ce est ce qu'on appelle MIME
type ou le type de contenu.
Et nous précisons dans la spécification ce que la cartographie doit être.
Mais vous avez besoin de traduire elle a finalement au code c.
>> Ensuite est notre fonction similaire charnu appelée parse, dont le but dans la vie
est à lire, pas d'un fichier, mais à partir d'une connexion réseau.
Plus précisément, la lecture et l'analyse de la requête HTTP qui est venue à partir d'un navigateur
au serveur de telle sorte que finalement, nous pouvons analyser
à seulement les en-têtes à la demande ligne et retourner ceux de vous
par l'intermédiaire d'un tampon global que nous avons déclaré ci-dessus [? principale. ?]
>> Reset, quant à lui, est un fonction que l'on définit
qui est appelé de manière itérative l'intérieur du principal chaque fois que vous êtes sur le
prêt à commencer à écouter pour une nouvelle connexion
afin que nous sachions toujours l'état de nos variables
et que nous avons aussi libérer toute mémoire qui
aurait été alloué pour une connexion de réseau précédent.
Ensuite, il ya commencer, le fonction que nous écrivions
qui contient un ensemble beaucoup de code de réseautage
qui commence finalement le serveur Web.
>> Dernière mise est la fonction appelé arrêt, qui
fait exactement cela, il arrête le serveur Web.
Mais d'abord, il libère toute la mémoire a ce encore été alloué.
Mais il appelle finalement sortie sans même rendre le contrôle
à notre fonction principale.
En fin de compte, l'un des la plupart des techniques importantes
la mise en œuvre de ce serveur Web est va être un peu d'essais et d'erreurs,
ayant une fenêtre ouverte navigateur à droite et une fenêtre de terminal au
à gauche, la console de serveurs fenêtre, de sorte que vous
peuvent voir les messages qui sont étant affichée sur l'écran.
>> Mais serait mieux encore un tiers fenêtre, une deuxième fenêtre de terminal,
dans lequel vous utilisez Telnet, l'utilisation pour lequel est prescrit dans la spécification.
Et Telnet est juste une très programme de réseau simple
qui vous permet de faire semblant de un navigateur dans une fenêtre
tout en parlant à l'autre fenêtre.
De cette façon vous pouvez voir exactement les commandes textuelles
qui sont de revenir du serveur au client
sans avoir à piquer autour du développeur de Chrome
outils dans une autre Interface clunkier.