« INFO625 : Réseau » : différence entre les versions

De Wiki du LAMA (UMR 5127)
Aller à la navigation Aller à la recherche
Ligne 55 : Ligne 55 :


le protocole UDP/IP ne gère par la fiabilité. On pourrait utiliser TCP/IP, mais on perdrait la possibilité de demander les messages à non reçu quelqu'un de proche de nous ... Voici donc une proposition de gestion distribuée de la fiabilité :
le protocole UDP/IP ne gère par la fiabilité. On pourrait utiliser TCP/IP, mais on perdrait la possibilité de demander les messages à non reçu quelqu'un de proche de nous ... Voici donc une proposition de gestion distribuée de la fiabilité :

# Stocker les messages dans un dossier local, avec un fichier associé à chaque pseudo. Il faudra ajouter une option pour contrôler le nom de ce dossier. Cela permet deux choses, garder trace des discussions anciennes et réexpédier n'importe quel message qui aurait été perdu par une machine. Conseil: sauvegarder les messages avec une taille fixe, ce qui perd un peu de place mais permet d'accéder directement au message numéro ''n'' avec <tt>fseek</tt>. (rappel les fonctions pour manipuler les fichiers dont vous aurez besoin sont <tt>fopen</tt>, <tt>fclose</tt>, <tt>fseek</tt>, <tt>fwrite</tt>, <tt>fread</tt> . Pour déterminer la taille du fichier (et donc le nombre initial de messgages, on pourra utiliser <tt>fseek</tt> et <tt>fpos</tt> ou bien <tt>stat</tt>. Remarque : on ne cherchera pas à ouvrir tous les fichiers au départ; on ouvrira le fichier corrspondant à un pseudo uniquement à la reception d'un message provenant de ce pseudo. De plus, il ne faut pas laisser trop de fichiers ouverts, donc on prendra soin de refermer les fichiers après usage.
==== Stockage des messages ====
# On détectera les messages perdus grâce au numéro de message de l'émetteur. Une fois détectée la perte d'un message, on le redemande à une machine prise au hasard sur le réseau de discussion, qui répond seulement si elle a le message. On fait cela avec un timeout. Voici le code permettant de générer un appel de fonction après un certain temps :

<code language="C">
Stockez les messages dans un dossier local, avec un fichier associé à chaque pseudo. Il faudra ajouter une option pour contrôler le nom de ce dossier. Cela permet deux choses, garder trace des discussions anciennes et réexpédier n'importe quel message qui aurait été perdu par une machine.
sighandler

</code>
Conseil: sauvegarder les messages avec une taille fixe, ce qui perd un peu de place mais permet d'accéder directement au message numéro ''n'' avec <tt>lseek</tt> (qui permet aussi d'agrandir le fichier).

Alternative: créer, pour chaque pseudo, un fichier d'index donnant la position du message dans un autre fichier (ça fait donc deux fichiers par pseudo).
Rappel : les fonctions pour manipuler les fichiers dont vous aurez besoin sont <tt>open</tt>, <tt>close</tt>, <tt>lseek</tt>, <tt>write</tt>, <tt>read</tt>. Pour déterminer la taille du fichier (et donc le nombre initial de messages, on pourra utiliser <tt>lseek</tt> ou bien <tt>stat</tt>. Remarque : on ne cherchera pas à ouvrir tous les fichiers au départ; on ouvrira le fichier correspondant à un pseudo uniquement à la réception d'un message provenant de ce pseudo. De plus, il ne faut pas laisser trop de fichiers ouverts, donc on prendra soin de refermer les fichiers après usage.
# On détectera les messages perdus grâce au numéro de message de l'émetteur. Une fois détectée la perte d'un message, on le redemande à une machine sur le réseau de discussion, qui répond seulement si elle a le message. Essayez de choisir la machine le mieux possible ... Si l'on imagine un message perdu pour presque toutes les machines, il faut mieux éviter de la redemander au même expéditeur. Il faudra aussi créer de nouveaux type de message pour les demandes de réexpédition et leur réponse. Remarque : que doit faire une machine recevant une demande de réexpédition pour un message qu'elle n'aurait pas reçu.

Note : on n'essaiera pas de redemander la réexpédition après un certain temps, d'abord parce que c'est un peu complexe et nécessite des éléments d'un cours du prochain semestre ... et aussi car on redemandera la réexpédition de tous les messages encore manquant à chaque reception d'un message pour le même pseudo.

Note bis : toute machine du réseau garde tous les messages passées et une machine qui se reconnecte après une absence redemandera tous les messages manquant pour une pseudo donné, dès qu'elle recevra un message de ce pseudo.

Version du 2 décembre 2010 à 21:24

Plan détailé du cours

Non encore disponible

TP 1

Objectifs Globaux

Il s'agit de comprendre la programmation d'applications réseau utilisant les protocoles TCP et UDP d'IPv4 (on ne s'intéressera pas malheureusement à IPv6 faute d'infrastructure réseau sur le site ... Il est pourtant possible d'adapter le code pour qu'il marche sur IPv4 et IPv6)

L'application sera une messagerie instantanée de paire-à-paire (Peer-to-Peer instant messagerie) utilisant UDP et implémentant la fiabilité de manière distribuée. On utilisera TCP pour la connexion initiale aux salles de discussion et, si le temps le permet, pour enregistrer les salles de discussions sur un serveur web afin de les rendre visibles.

Vous serez évalué sur un compte-rendu répondant aux questions (en gras) de ce document et le rendu de votre programme par mail.

ATTENTION : si votre programme ne compile pas vous serez noté seulement sur le compte-rendu. De plus, chaque warning avec les options -Wall -pedantic -std=c99 enlève 1 point.

Préliminaires

Utiliser les commandes Unix ifconfig, route et arp -a pour connaître la configuration de votre machine. Utiliser ping et traceroute entre les machines fixes de la salle et les portables en vpn pour découvrir une partie de l'achitecture réseau de l'université. Notez vos conclusions.

Compilation et analyse du programme initial

Le programme initial est constitué d'un seul fichier p2pchat.c que vous pouvez compiler avec la commande:

$ gcc -o p2pchat -Wall -pedantic -std=c99 p2pchat.c

Lorsque vous lancez le programme en tapant

$ ./p2pchat mon_pseudo_favori

Tout ce que vous tapez est vu par les autres sur le même sous-réseau et vice-versa (les messages sont envoyés ligne par ligne. Pour terminer la conversation, il faut taper Ctrl-D qui ferme le fichier d'entrée standard stdin.

Vous pouvez changer le port avec l'option --port numero_de_port si vous voulez pouvoir faire des salles de discussions séparées (chaque numéro de port correspondra à une salle différente).

Ce programme d'un peu moins de 200 lignes contient quelques fonctions auxiliaires qui n'ont pas grand chose à voir avec le réseau et d'autres fonctions qui s'occupe de la communication. Voici un synopsis du mécanisme de communication via les sockets, dans le cas particulier d'UDP/IP:

  1. On crée un socket avec la fonction socket. Un socket est un descripteur de fichier (un entier donc) dans lequel on peut lire et écrire, mais ces lectures et écritures correspondent respectivement à des réceptions et émissions sur le réseau. On peut changer quelques options de ce socket avec la fonction setsockopt.
  2. On relie ce socket à notre propre adresse, cela est indispensable car la même machine peut avoir beaucoup d'interfaces réseaux différentes (ethernet, wifi, bluetooth, ...), utilisant des protocoles de communications parfois différents.
  3. En UDP, on peut alors lire et écrire dans le socket avec les fonctions sendto et rcvfrom car le mode UDP est sans connexion.

Identifiez les différentes fonctions de notre programme s'occupant du réseau et tentez à l'aide des pages de manuels des fonctions citées ci-dessus d'anaysez ce qu'elles font, de manière assez surperficielle, car il y a de nombreux détails subtiles ... Notez vos conclusions.

  • Quel est la convention utilisée pour les messages sur le réseau ?
  • La taille maximum des messages n'est pas garantie (MAX_MSG). Trouvez l'origine de ce problème et corrigez le.

Gestion distribuées de la fiabilté

le protocole UDP/IP ne gère par la fiabilité. On pourrait utiliser TCP/IP, mais on perdrait la possibilité de demander les messages à non reçu quelqu'un de proche de nous ... Voici donc une proposition de gestion distribuée de la fiabilité :

Stockage des messages

Stockez les messages dans un dossier local, avec un fichier associé à chaque pseudo. Il faudra ajouter une option pour contrôler le nom de ce dossier. Cela permet deux choses, garder trace des discussions anciennes et réexpédier n'importe quel message qui aurait été perdu par une machine.

Conseil: sauvegarder les messages avec une taille fixe, ce qui perd un peu de place mais permet d'accéder directement au message numéro n avec lseek (qui permet aussi d'agrandir le fichier).

Alternative: créer, pour chaque pseudo, un fichier d'index donnant la position du message dans un autre fichier (ça fait donc deux fichiers par pseudo).

Rappel : les fonctions pour manipuler les fichiers dont vous aurez besoin sont open, close, lseek, write, read. Pour déterminer la taille du fichier (et donc le nombre initial de messages, on pourra utiliser lseek ou bien stat. Remarque : on ne cherchera pas à ouvrir tous les fichiers au départ; on ouvrira le fichier correspondant à un pseudo uniquement à la réception d'un message provenant de ce pseudo. De plus, il ne faut pas laisser trop de fichiers ouverts, donc on prendra soin de refermer les fichiers après usage.

  1. On détectera les messages perdus grâce au numéro de message de l'émetteur. Une fois détectée la perte d'un message, on le redemande à une machine sur le réseau de discussion, qui répond seulement si elle a le message. Essayez de choisir la machine le mieux possible ... Si l'on imagine un message perdu pour presque toutes les machines, il faut mieux éviter de la redemander au même expéditeur. Il faudra aussi créer de nouveaux type de message pour les demandes de réexpédition et leur réponse. Remarque : que doit faire une machine recevant une demande de réexpédition pour un message qu'elle n'aurait pas reçu.

Note : on n'essaiera pas de redemander la réexpédition après un certain temps, d'abord parce que c'est un peu complexe et nécessite des éléments d'un cours du prochain semestre ... et aussi car on redemandera la réexpédition de tous les messages encore manquant à chaque reception d'un message pour le même pseudo.

Note bis : toute machine du réseau garde tous les messages passées et une machine qui se reconnecte après une absence redemandera tous les messages manquant pour une pseudo donné, dès qu'elle recevra un message de ce pseudo.