TD 7 - Réseau

L’objectif de ce TD de finir d’aborder la communication sur réseau par les sockets, en exploitant les connaissances vues au cours des TDs précédents.

1. Les bases d’un serveur

Cet exercice a pour but d’ouvrir une partie de la connexion réseau (celle du serveur, connexion appelée socket).

Créez un programme qui établit attend une connexion (qu’on établira avec telnet) et quitte. Les étapes sont les suivantes:

  1. Création d’une socket avec socket(2). Ouvrir une socket pour communiquer sur internet (IPv4, flag AF_INET) en mode connecté, duplex (flag SOCK_STREAM) et laissez le système choisir le protocole (flag 0). La socket sera fermée à la fin du programme par un appel à close(2)
  2. Initialiser une structure sockaddr_in qui contient les champs:
  • sin_family: utiliser AF_INET pour protocole internet
  • sin_addr.s_addr: utiliser INADDR_ANY pour que le système choisisse l’adresse internet de la machine
  • sin_port: le numéro du canal de communication, appelé port. C’est un entier quelconque, >1024. Attention, utiliser les convertisseurs htons(3),... pour que le codage des entiers soit bien celui du réseau, pas celui de la machine.
  1. Associer une adresse à la socket précédemment créée en passant la structure sockaddr_in et la socket à bind(2).
  2. Se mettre à l'écoute des connexions avec listen(2) et spécifier le nombre d’entrées dans la file d’attente des demandes de connexion.
  3. Accepter (et attendre) une connexion entrante avec accept(2). Les deux derniers arguments seront mis à nul. Le descripteur de socket retourné peut être manipulé comme un descripteur de fichier.
  4. Dès qu’une connexion est acceptée (utiliser telnet pour établir une connexion), fermer le descripteur de socket retourné par accept(2) et par socket(2).

Serveur echo

Un serveur echo accepte les connexions comme dans l’exercice précédent et renvoie au client tout ce qu’il a reçu, tant qu’il ne reçoit pas “quit”. Quand il reçoit “quit”, il ferme la communication avec le client et se remet en attente d’autres connexions. Les échanges avec les clients qui se connectent se font grâce à read(2) et write(2) sur le descripteur obtenu par accept(2).

  • Ecrivez à partir de l’exercice précédent un serveur echo.
  • Lancez plusieurs clients avec telnet simultanément. Que se passe-t-il ?
  • Modifiez le serveur à l’aide de fork(2) pour pallier ce problème.

Serveur web

Un serveur web accepte les connexions comme dans l’exercice précédent. Le protocole est le suivant:

  • Le client (navigateur) lui envoie une chaîne de caractères, contenant notamment la séquence GET fichierfichier est le fichier à récupérer par le serveur web (un fichier html par exemple).
  • Le serveur renvoie la chaine
HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n

suivie du contenu du fichier

Le type du fichier peut être adapté (ici text/html) suivant qu’il s’agit d’un fichier html, jpg, png…

  • Ecrivez un serveur web. Vous utiliserez stat(2) pour savoir si le fichier demandé existe et avoir sa taille, et mmap(2) pour le mettre en mémoire et ainsi l’envoyer avec write(2).
  • Réécrire le serveur pour qu’il soit multithreadé. Pour ce faire, on créera un nouveau thread pour traiter chaque connexion.
  • Modifier la solution précédente pour créer 8 threads dès le départ. Ces threads sont placés au début en attente, et ne sont activés que lorsqu’il y a des connexions à traiter. C’est un exemple du problème producteur/consommateur: le producteur est le serveur, qui “produit” des requêtes à traiter, les threads sont les consommateurs et traitent ces requêtes. Adapter la solution à ce problème au programme.