DAVID MALAN: Maintenant, nous allons jeter un examiner la répartition réelle code dans le fichier appelé server.c. Maintenant, gardez à l'esprit que ce assez grande cette semaine de fichier. Il est plus de 1000 lignes de code, mais la plupart de ces lignes que nous avons écrit. Et ce que nous avons laissé est quelques blancs que vous aurez besoin de remplir d'ajouter certains des plus fonctionnalités intéressantes du serveur web pour réellement faire démarrer. En effet, si vous exécutez la distribution code après le compiler vous verrez que le serveur Web ne pas le faire tant que ça. Au lieu de cela, l'utilisateur obtient un 501, pas mis en œuvre, message d'erreur. Mais cela devrait donner un sens parce nous avons en effet pas mis en œuvre ensemble de ses fonctionnalités. Donc, nous allons jeter un oeil à server.c. Et vous aurez envie d'aller plus cela dans un peu plus en détail, un peu plus lentement, à votre propre rythme. Mais pour l'instant je vais essayer de guider vous à travers elle pour vous donner un sens de ce qui est utile pour savoir, ce qui est moins utile de savoir, de sorte que vous pouvez guider votre propre exploration. Alors au sommet de server.c, bien sûr, nous avons tout un tas d'définit. Ainsi que tout un tas de comprend. À noter est que nous avons quelques constantes globales ici, que nous utilisons dans notre code pour le rendre en sorte que certains tableaux sont de longueur suffisante. Basé sur combien de temps les requêtes HTTP nous attendre à être recevoir, potentiellement, à partir de clients Web, ou les navigateurs. Pendant ce temps, nous allons faire défiler vers le bas sur ici, pour une définition de type. Notez que comme dans P set 4, lequel nous avons joué avec le fichier I / O, de même ici, nous sommes jouant avec beaucoup d'octets. Et donc nous avons typedeffed carboniser être un octet. En d'autres termes, le type de données, le capital B-y-t-e, ne existe pas par défaut en C. Nous avons donc créé comme un synonyme de omble de sorte que nous avons une valeur de 8 bits avec lesquelles travailler. Maintenant, il ya tout un tas de prototypes ici, dont quelques-uns sont les fonctions que vous allez écrire, mais plupart d'entre eux nous nous avons écrit. Disons faites défiler maintenant, enfin, quelques variables globales. On est cette étoile de char, Alias ​​racine. En effet, vous remarquerez que nous ne sommes pas en utilisant la bibliothèque CS50 plus. Donc, nous sommes à la place juste en utilisant l'omble étoiles. Et racine est va être un pointeur vers la chaîne représente la racine du serveur. Ainsi, par exemple, quand je exécuté la commande précédente et spécifié la racine du mot «public», ce répertoire à l'intérieur de la distribution code. Root, ici, serait un pointeur exactement cette chaîne, «public». Ou vraiment le chemin complet / home / ubuntu / ainsi de suite dans ce répertoire public. Pendant ce temps, dans la ligne 67 ici, nous avons ce qu'on appelle des descripteurs de fichiers. Ceux-ci sont dans le même esprit de déposer des pointeurs étoiles. Mais il se trouve qu'il ya un autre ensemble de fonctions vous pouvez utiliser avec la lecture de fichiers ou lecture de connexions réseau. Comme une toile de serveur web connexion navigateur effectivement utilise tout entiers à la place des pointeurs, comme nous l'avons vu sur P Set 4. Mais il est la même idée. Et je l'ai fait ces échelle mondiale pour continuer piste d'un descripteur de fichier client. Comme un pointeur à mon client Web. Et un descripteur de fichier du serveur. Sorte d'un pointeur vers le serveur web, mais ils ne sont pas réellement des pointeurs, ils sont juste des chiffres. Enfin, nous avons cette mondial la variable appelée ici signalée. Quelle est ma façon, la vraie ou faux, de garder piste de si l'utilisateur a a signalé qu'il ou elle veut pour arrêter le serveur web. Et en effet, il ya une fonction qui écoute pour le contrôle C. Alors que si vous, l'utilisateur, veulent tuer le serveur en frappant de contrôle C, que vous aurez variable booléenne voir dans le code est mis à true. Et puis dans une boucle nous gardons vérifier la valeur de cette variable. Et si il est vrai, nous avons juste de cesser complètement le programme. Prenons maintenant un regard sur principale. Vous ne devez comprendre tout en principal, mais nous allons vous donner une idée de l'ensemble du flux. Et alors jetez un oeil de plus près vous-même à certains des commentaires. En premier lieu, façon de partie grâce principale, nous analysons les arguments de ligne de commande. Il se trouve que le principal est va attendre soit à bord h de l'aide, qui vous explique comment tout pour exécuter le programme de façon très succincte. Ou un tiret p, ce qui permet de vous spécifiez un port. Mais encore une fois, en utilisant la port 80 80, par défaut, est ce que vous devez utiliser CS 50 IDE. Ensuite, nous venons de faire quelques vérifications d'erreur. Faire en sorte que la valeur de port est en effet comme nous le prévoyons, dans une gamme particulière. Et puis peu de la magie commence. Nous appelons cette fonction Start, qui nous avons écrit. Nous passons dans avec le port, comme ainsi que tous les arguments optionnels afin de démarrer le serveur. Plus précisément, ce numéro de port. Tout droit, à côté, cela est assez cryptique code qui vous ne verrez pas trop souvent, mais il est une façon élégante de révélateur le programme à écouter pour un signal. Un signal étant quelque chose comme un AVC touche spéciale, comme le contrôle C. Donc, ce code est de savoir comment nous enregistrons ce qu'on appelle un écouteur d'événement. De sorte que, quand l'utilisateur appuie sur Contrôle C ce code indique à l'ordinateur pour exécuter une fonction appelée gestionnaire. Qui est écrit plus bas, mis en œuvre plus bas dans ce fichier, server.c, qui arrête complètement le programme. Mais ne vous inquiétez pas à propos de les détails internes là. Concentrons-nous maintenant sur la boucle interne. En effet, ce que le serveur web est en train de faire est délibérément boucle infinie. Parce que, après tout ce qui est à peu près ce que vous voulez un serveur web à faire. Jusqu'à ce que vous explicitement arrêter, vous voulez juste pour y être assis efficacement dans une boucle, attendant que quelqu'un sur le Internet pour se connecter à elle. Alors que le serveur Web peut puis répondre à certaines demande. Maintenant, remarquez au sommet du programme Je gratuitement certaines variables, parce que plus tard vous aurez nous voyons avec malloc dans certains endroits. Donc, je veux juste faire vous que tous mes variables sont initialisés à des valeurs connues. Ici-bas, je vérifie si la programme a été signalé. En d'autres termes, si l'utilisateur le contrôle frappé C, disons simplement quitter sur cette boucle en appelant arrêt. Et puis maintenant ce code obtient un peu plus intéressant. Mais notez que vous ne devez pas d'écrire quoi que ce soit dans le principal. Plutôt, à l'intérieur de la principale nous faisons ce qui suit. Si l'utilisateur a connected-- cela est une fonction que nous avons écrit, qui retourne vrai ou faux. Et chaque fois qu'il est appelé il dit seulement, oui, un client, un navigateur est connecté au serveur. Ou, non, il n'a pas. Et de cette manière que nous venons boucle infinie attente pour vrai à renvoyer par cette fonction. Pendant ce temps, cette fonction suivante, demande, nous a également écrit pour vous. Cela prend tout ce qui est à l'intérieur de cette enveloppe virtuelle, que l'on appelle HTTP demander, et effectivement il analyse pour ainsi dire. En regardant cela de haut en bas, de gauche à droite, et les charges tous ces premières lignes. Comme la ligne de get et rien d'autre en dessous, dans une variable que nous avons appelé message. Pour un message HTTP. Et nous avons également chargé sa longueur en longueur. Maintenant, cela est un peu différent. Donc, nous allons jeter un coup d'œil à ce sujet. Même si vous ne le faites pas avoir à mettre en oeuvre la demande, il est utile, peut-être, comprendre comment il fonctionne. Cette demande de la fonction apparemment est prise dans deux arguments, un message et la longueur. Mais remarquez que je suis de passage dans un esperluette à la fois un message et de la longueur. Mais si nous défiler vers le haut, ce qui sont un message et de la longueur? Eh bien remarquer que message et longueur sont déclarés à l'intérieur du principal d'être une star char. Et une taille t. Qui est vraiment juste un int, respectivement. Alors, quel est curieux ici, cependant, est que si le message est une étoile char mais je suis de passage dans des esperluette message, qui est une sorte de technologie obtenir l'adresse d'un pointeur. Un double pointeur, si vous voulez. Et en fait, si je fais défiler vers le bas. Chemin vers le bas dans ce fichier, où demande est effectivement mis en oeuvre, Je vais voir ce qui suit signature, ou un prototype, pour cette fonction. Que vous avez probablement jamais vu auparavant. La fonction de requête renvoie un booléen. Voilà probablement familier. Mais remarquez son premier argument. Il a appelé un message, mais je aurait pu appelé quelque chose ici. Mais il est star omble. Et cela est une sorte de chose intéressante. Parce que je veux cette fonction demander à allouer de la mémoire toutefois grand pour la requête HTTP en ce que l'enveloppe est virtuel qu'il reçoit à partir du navigateur, je veulent être en mesure de retourner une chaîne. Mais je veux aussi être capable de retourner une longueur. Donc, comme vous le verrez dans le spécification, C, bien sûr, ne peut pas renvoyer plusieurs valeurs. Et en fait, je suis seulement retournant un booléen ici. Mais tout comme nous avons vu dans Lecture à dos pendant que vous peut retourner deux valeurs si vous passer deux valeurs de référence. Ou par pointeur. Alors que vous pouvez réellement aller à ces adresses, mis valeurs là, et de manière efficace à travers ce voie de retour, pour ainsi dire, peut faire un retour de la fonction des valeurs multiples à l'appelant. Dans ce cas, la demande peut retourner trois valeurs. Son type de rendement réel, un booléen. Le message, une étoile char étoiles. Et la longueur, une taille t. Qui est juste un int. Parce que cette demande de fonction peut aller à la longueur de l'adresse et de mettre une valeur il. Et il peut aller à l'adresse de message et mettre une valeur il. Et que maintenant doit avoir un sens. Parce que même si un message est une étoile char étoiles, dès que vous y allez avec le message d'étoiles, que nous avons vu auparavant dans le code, qu'allez-vous y trouver? Vous allez trouver attendant vous là, un morceau de mémoire devrait être une star char. Ou l'adresse d'une chaîne. Et il est OK si vous ne le faites pas assez enveloppement votre esprit autour de ce trop rapidement. Mais considérer que tout ce que nous faisons est de prendre l'adresse d'un pointeur afin que nous puissions y aller et effectivement mis un pointeur là. Mais ne vous inquiétez pas si ce ne fait pas couler en ce moment. Savons pour l'instant que le fonction de la demande effective vous offre ces trois valeurs. Passons donc maintenant de retour à principal. Que se passe sur la prochaine, en principale, est la suivante. Une fois que je l'ai eu à l'intérieur des messages et la longueur, les deux valeurs que je soucient. Ensuite, nous allons de l'avant et à écrire du code pour vous que vous permet de lire seulement la première ligne. La demande dite ligne de la demande. Plus précisément, quelque chose comme GET / HTTP 1.1, et rien de plus. Donc, il ya tout un tas de d'autres en-têtes HTTP, rappel, qu'un navigateur envoie à partir de un client à un serveur. Nous sommes juste en ignorant tous ceux sorte que tout ce que vous voyez sur la fenêtre de terminal, rappel, est juste quelque chose comme, get / Hello.html HTP / 1.1. Donc remarquer cependant, que ceux-ci trucs que nous faisons ici vont être utile, peut-être, dans votre propre fonction d'analyse qui vous allez mettre en œuvre. Remarquez comment que je suis juste déclarer une variable. Arrive à être const, ce qui signifie, Je promets de ne pas changer cette situation. Appelé botte de foin. Puis je habilement nommé mon prochain aiguille variable de sorte que je peux regarder proverbialement une aiguille dans une botte de foin, en utilisant un super pratique fonction appelée str str. S-T-R S-T-R, qui par son homme page ou par reference.CS50.NET, vous permet de rechercher des une corde dans un autre. Et ceci est ma façon de la recherche de la fin d'une ligne de sorte que je peux réellement lu juste une ligne dans la mémoire. Pendant ce temps, remarquez sur ligne 176 ici, je fait allouer suffisamment de mémoire pour cette ligne. Et puis en utilisant str et la copie, et en utilisant seulement une notation de support de rayons, dois-je ranger dans ce tableau? Exactement ce que la première ligne. En fait, permettez-moi de simplement sauter sur rapidement du cahier des charges ensemble de problème six. Ne lire cela en détail. Mais ce que vous trouverez est cette ligne particulière ici. Grâce à quoi basé sur la spécification la définition formelle HTTP nous spécifions ce que la première ligne doit être de tout navigateur à un serveur à l'intérieur de ladite dite enveloppe virtuelle. Plus précisément, le navigateur devrait mentionner une méthode, comme un get, ou par la poste, ou similaire. Puis littéralement un espace, représenté ici avec juste sp de sorte qu'il est explicite nous voulons vraiment un espace ici. Puis demander cibles qui être quelque chose comme /hello.HTML. Suivi par un autre espace. Suivi par une version. Ce qui serait quelque chose comme HTTP / 1.1. Suivi par C-R-L-C. Qui est un sigle vous allez voir beaucoup dans la description. Et ceci est juste une façon élégante de disant r barre oblique inverse, barre oblique inverse n. En d'autres termes, le chariot retourner, nouvelle ligne. Ou saut de ligne. Retour chariot, saut de ligne. Voilà ce que C-R-L-F signifie. Maintenant, quant à lui, si nous revenir à notre code, Voyons ce qui reste à faire pour vous. A l'intérieur de la principale, enfin, il ya Un appel à une fonction d'analyse. Le but de parse est de prendre ce que première ligne, dont la définition nous juste vu sur la spécification, et extraire la voie dite absolue et requête. Maintenant, jetez un oeil à la spécification pour ce que nous entendons par là. Mais dans la longue histoire courte, cette chose ici, la demande cible, est une chaîne qui peut être divisé en deux parties. Ou un chemin absolu comme /hello.HTML. Suivi par un point d'interrogation en option. Et puis quelque chose comme q égaux chats, ou q est égal à chiens, ou un certain nombre de valeur de clé paires que nous avons vu dans la leçon faisant partie de la paramétrisation d'une requête HTTP. Donc ce que vous allez avoir besoin à faire est de mettre en œuvre l'analyse. Et comprendre comment itérer sur ligne, qui est tout simplement le premier argument que nous passons en. Caractère pour le caractère pour le caractère. Seulement allant jusqu'à la fin de cette chaîne. Vous recherchez ce chemin absolu et à la recherche pour cette requête. Et ce qui est bien sur le fait que Nous vous avons donné dans la documentation cette définition grammaticale de cette première ligne, ici vous allez avoir à comprendre sur, eh bien, ce qui est la méthode. Est valide ou non? Et nous vous disons dans la spec quand elle est ou non valide. Recevez, par exemple, sera valable. Espace sera facile à vérifier. Tout en utilisant deux semaines style ou problème mettre deux vérification de chaîne de style. Ou le caractère de contrôle. Demande cible est la chose vous allez vouloir analyser. Alors jetez un oeil à la spec pour ce qu'il est attendu. Et puis enfin, HTTP version, vous voulez juste pour vous assurer qu'il est parmi les versions prises en charge comme HTTP 1.1. Donc, essentiellement, d'une fonction d'analyse de va être une occasion se contenter de lire ce caractère de chose pour le caractère pour caractère, ou corde par corde, en veillant qu'elle corresponde à la présente spécification. Tout droit, Retour au menu principal. Voyons ce qu'il en reste. Donc, supposons que vous avez maintenant mise en œuvre de votre fonction d'analyse. Nous avons analysé en sortir cette soi-disant chemin absolu et la requête, ce qui ne principale doivent maintenant faire avec ça? Eh bien, un, vous verrez dans le code que nous URL décodé au cas où le navigateur a certains caractères spéciaux codés et de façon particulière, nous allons de l'avant et de convertir ceux qui reviennent les caractères ASCII appropriées. Ensuite, nous allons de l'avant et voir si l'utilisateur a demandé /hello.HTML, ce fichier ne signifient-ils vraiment? En d'autres termes, nous devons prendre la racine du serveur, ce chemin vers le répertoire public et concaténer avec quelque chose comme, Hello.html. Alors que nous avons un plus grand chaîne qui nous amène exactement dans le fichier de Hello.html réel sur IDEs CS50 disque dur ou disque. Ensuite, nous vérifions que le chemin existe réellement. Sinon, nous lançons une 404 erreur pour l'utilisateur. Et en effet, tout au long de notre code, vous verrez beaucoup d'utilisations de cette erreur fonction qui nous nous a écrit, et la spécification vous guide à travers. Ceci est juste un moyen de revenir autre chose que 200 à l'utilisateur. Maintenant, ici-bas, je vais de l'avant et comprendre est ce que l'utilisateur a demandé un fichier ou un répertoire. Parce que si elle est un répertoire, je envie de faire une ou deux choses. Premièrement, si l'utilisateur visite un URL qui est pour un répertoire, mais ne se termine pas par une barre oblique, pour des raisons classiques, Je tiens à vous assurer que nous changeons l'URL à fait terminer par un slash. Et vous le verrez dans la source code que nous vous avons donné, nous forçons à l'utilisateur de rediriger de ne pas [? fu?] mais [? fu /,?] si elles ont fait que. Et voir le descriptif en conséquence. Pendant ce temps, nous vérifions une autre chose. Si l'utilisateur a visité un répertoire et ce répertoire contient un fichier appelé index.html index.php ou, par convention humaine nous ne voulons pas de leur montrer la contenu de ce répertoire. Nous voulons leur montrer le contenu de ce fichier par défaut, index.html ou index.php. Et si le code que je l'ai appels mis en évidence ici une fonction appelée index qui vérifie simplement, Existe-il un fichier ici nommé index.html ou index.php. Dans le cas contraire, si aucun des ces conditions sont applicables nous appelons tout simplement fonction liste, qui nous avons écrit, qui énumère littéralement le contenu d'un répertoire. Tout à droite, et si la demande que le navigateur de l'utilisateur a fait est pas pour un répertoire, mais pour un fichier? Eh bien, tout d'abord que nous appelons une fonction de recherche. Qui va dire à la serveur, est-ce un JPEG, est-ce un fichier HTML, est-ce une GIF, ou un autre format. Si oui, il est ensuite aller vérifier, ainsi, est-il un fichier PHP. Si oui, nous voulons appeler une fonction appelés interpréter, que nous avons écrit, qui interprète ce fichier PHP et recrache les résultats. Ou, plus convaincante, si elle est quelque chose d'autre, Allons de l'avant et simplement transférer le fichier. Comme le GIF ou JPEG à partir du serveur à l'utilisateur, comme si ils ont demandé une page HTML, l'image, ou tout nombre d'autres choses. Enfin, si rien ne semble d'autre travail, nous allons juste-à-dire 501. Qui est que 501, pas mis en œuvre message, signifiant que le serveur est pas encore terminée.