TP7 (Socket Avançé)
L'objectif de ce TP est de vous faire développer un serveur web minimaliste, respectant le protocole HTTP et pouvant fonctionner avec un navigateur web standard comme Firefox.
Un peu de documentation sur le protocle HTTP :
Requête Cliente (GET)
Lancez la commande “netcat -l 8080”. Lancez le navigateur web firefox et tapez l'URL “http://localhost:8080/index.html”. Qu'observez-vous ?
Interprétez les différentes lignes en vous aidant de Wikipedia :
Réponse du Serveur
A l'aide de Telnet, produire une requête GET pour obtenir la page d'accueil d'un serveur web comme celui du LaBRI (http://www.labri.fr).
Voici un exemple de réponse, composé d'un entête HTTP et de la réponse HTML séparée par un saut de ligne.
HTTP/1.1 200 OK Date: Thu, 18 Mar 2010 19:48:03 GMT Server: Apache Expires: Tue, 01 Jan 2002 00:00:00 GMT Cache-Control: no-store, no-cache, must-revalidate Set-Cookie: userlang=fr; path=/ Vary: Accept-Encoding Content-Length: 21049 Content-Type: text/html; charset=ISO-8859-1;
<!DOCTYPE html PUBLIC ... > <html> <head> ... </head> <body> ... </body> </html>
Reproduisez l'expérience avec Telnet en demandant une page qui n'existe pas. Quelle est la réponse ?
Programmation d'un serveur web
En utilisant l'exemple de serveur fourni au TP 6, programmez un serveur web minimaliste qui renvoie les documents web contenus dans le répertoire d'accueil www/.
Lors d'une requête GET pour un certain document, il y a trois cas à traiter :
- la requête concerne un fichier d'extension .html : dans ce cas, on répond simplement ce document.
- la requête concerne un répertoire : dans ce cas, on répond une page web contenant la liste des fichiers contenus dans ce répertoire (sous forme de liens hypertextes) ou on répond le fichier “index.html” si ce dernier existe.
- la requête concerne un document qui n'existe pas : dans ce cas, on répond une erreur 404 (par exemple, un fichier “404.html”).
A la fin du traitement, la connexion est systématiquement fermée.
Compléments
Voici un extrait de code qui vous montre comment lister le contenu du répertoire courant et comment différencier les fichiers réguliers des répertoires.
#include <sys/types.h> #include <dirent.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> DIR * dir = opendir("."); struct dirent * entry; while((entry = readdir(dir)) != NULL) { char * path = entry->d_name; struct stat info; stat(path, &info); if (S_ISDIR(info.st_mode)) printf("[dir] %s\n", path); else if (S_ISREG(info.st_mode)) printf("[file] %s\n", path); }
Pour tester si le fichier “index.html” existe dans le répertoire “path”, on peut s'inspirer de l'extrait de code suivant :
struct stat info; char filename[255]; filename[0] = 0; strcat(filename, path); strcat(filename, "/index.html"); int ret = stat(path, &info); if(ret == 0) printf("%s found\n", filename);