:: Enseignements :: ESIPE :: INFO2 :: 2014-2015 :: Programmation système en C ::
| Écouter des chaussettes |
Exercice 1 - DeNiSe
Cet exercice préparatoire consiste à manipuler les réponses fournies par le DNS. Pour travailler
avec les sockets, vous devez utiliser plusieurs structures, et y copier des informations obtenues
dans d'autres structures. Ce premier exercice consiste en la ré-ecriture de la commande host. Celle-ci
interroge le DNS avec le primitive
struct hostent *gethostbyname(char * ip-name) (ip_name étant
en l'occurrence le nom de la machine que vous recherchez, saisie sur la ligne de commande. La structure
obtenue contient le nom de la machine (pas toujours identique à celui que vous avez demandé). Ensuite vient
la liste de tous les aliases de cette machine... Puis la liste des adresses de cette machine (h_addr étant
l'adresse indiquée par le DNS) : Attention concernant les adresses, elles sont exprimées en binaire (et non
décimal pointé).
inet_ntop va vous permettre de l'afficher sous la forme aaa.bbb.ccc.ddd.
Exercice 2 - My Firefox
On souhaite récupérer la page d'accueil du site
www.google.com. Pour cela, il faut se connecter sur le port 80
du serveur correspondant, envoyer la bonne requête HTTP et afficher tout ce qui nous est renvoyé:
- créer une socket avec l'appel système du même nom, spécifier la famille d'adresse correspondant à
Internet (AF_INET ou PF_INET), demander une socket en mode connecté
(SOCK_STREAM), avec le protocole par défaut. Vérifier le résultat de l'appel système.
- remplir une struct sockaddr_in de façon à indiquer qu'on veut se connecter sur le port 80
(correspondant au service http) du serveur. Il faudra utiliser la fonction htons() pour convertir
le numéro de port dans le bon format.
Quant au champ sin_addr, il ne contient qu'un entier (s_addr), qu'il faudra
remplir en résolvant l'url avec gethostbyname() (vu précédement) et recopiant avec
memcpy le champs h_addr de la structure retournée.
struct sockaddr_in {
short sin_family; // AF_INET
unsigned short sin_port; // htons(port)
struct in_addr sin_addr; // voir struct in_addr
char sin_zero[8]; // bourrage
};
struct in_addr {
unsigned long s_addr; // sert à représenter l'adresse
};
connecter la socket avec l'appel système connect(), envoyer la requête
"get http://www.google.com HTTP/1.0\n\n", puis lire sur la socket et afficher les données lues.
Exercice 3 - Le premier serveur de Martine
On souhaite maintenant implémenter un serveur très simple. Pour cela, on va créer une socket en écoute.
- réutiliser l'appel système socket(), puis, utiliser bind() afin de spécifier
le port sur lequel on veut écouter. Donner un port au dessus de 1024 (les ports en dessous de 1024 sont
réservés au root) dans le champ adresse de la structure à fournir à bind(), mettre INADDR_ANY
qui signifie qu'on veut écouter sur toutes les interfaces de la machine.
- après le bind(), mettre la socket en écoute avec listen(). Puis, faire un accept().
Le programme se bloque, jusqu'à ce qu'on se soit connecté sur le port qu'on avait spécifié à bind()
(en faisant, par exemple, telnet localhost numero_de_port). Vérifier que le programme se débloque
bien au moment où l'on fait le telnet.
- l'appel à accept() renvoie une nouvelle socket. L'ancienne reste bien en écoute, mais
la nouvelle représente la connexion nouvellement établie. En faisant un simple write(),
envoyer un message sur la socket, et vérifier que lorsqu'on fait le telnet, on reçoit bien le message.
- faire une communication très simple entre le telnet et le serveur. Par exemple le serveur demande
d'entrer son nom, puis affiche bonjour, le_nom et déconnecte l'utilisateur. Puis le serveur
attend une nouvelle connection (revenir dans la boucle accept()).
© Université de Marne-la-Vallée