:: Enseignements :: Master :: M1 :: 2012-2013 :: Programmation d'Applications Réseaux ::
[LOGO]

Multi File Transfer - MuFiT


L'objectif est d'implémenter un serveur et des clients permettant de transférer simultanément différents fichiers en utilisant le protocole UDP pour les données et TCP pour les commandes et le contrôle.
Vérifiez que vous êtes bien dans la liste des binômes enregistrés. Dans le cas contraire, faites vous connaitre auprès de etienne.duris[at]univ-mlv.fr.

Vous avez jusqu'au mardi 12 mars 2013 pour constituer votre binôme, après quoi, il sera trop tard et votre projet ne pourra pas être corrigé (il sera noté 0/20).

La date limite de rendu du projet est fixée au 16 avril 2013, selon les modalités décrites en bas de cette page. Une soutenance aura lieu l'après-midi du vendredi 19 avril 2013. Les réponses aux questions posées individuellement sont publiées ici.

Serveur MuFiT

Le serveur MuFiT propose en téléchargement un ensemble de fichiers présents dans un répertoire donné. Le serveur écoute sur un port TCP pour accepter les connexions des clients: sur cette connexion, un client peut envoyer des commandes ou recevoir des informations de contrôle, mais les données des fichiers doivent circuler dans des datagrammes UDP (en dehors de la connexion TCP). Chaque fichier sera donc transféré sous la forme de tronçons successifs, définis par le décalage de leur premier octet et leur taille.

Pour avoir des idées sur des techniques de découpage d'un fichier en tronçons UDP, on pourra lire la RFC 1350 du protocole TFTP. Attention : notre contexte est spécifique et TFTP ne convient pas pour implémenter MuFiT!

Le serveur doit pouvoir gérer plusieurs clients simultanément: non seulement leurs connexions TCP, mais également les transferts de fichiers en UDP correspondant à leurs commandes.

Le serveur sera exécutable via une fonction main implantée dans la classe fr.upem.mufit.server.MuFiTServer et acceptera (au moins) les arguments suivants :
  • p port : port d'écoute TCP du serveur (obligatoire)
  • d directory : répertoire racine de l'arborescence des fichiers servis (obligatoire)

Le serveur dispose d'un ensemble de commandes via l'entrée standard dans un petit langage de script qui devra comprendre au moins les commandes suivantes :
  • users : affichage des clients actuellement connectés en TCP
  • current : affichage des téléchargements en cours et leur état (pourcentage), chaque téléchargement étant identifié par un entier
  • kill num : interrompt le téléchargement dont l'entier est spécifié
  • mput file : initie la diffusion en multicast du fichier file à tous les clients connectés
  • stop : demande l'arrêt du serveur, celui-ci devant signaler proprement son extinction aux clients et couper ensuite les connexions.

Le serveur TCP des connexions avec les clients devra obligatoirement être implémenté en non-bloquant avec les entrées-sorties de java.nio.

Client MuFiT

Un client MuFiT permet de se connecter à un serveur MuFiT en utilisant l'adresse et le numéro de port TCP sur lequel ce dernier écoute. Il sera exécutable via une fonction main implantée dans la classe fr.upem.mufit.server.MuFiTClient et acceptera (au moins) les arguments suivants :
  • a address : adresse IP du serveur à contacter (obligatoire)
  • p port : port TCP du serveur à contacter (obligatoire)
  • d directory : répertoire racine de l'arborescence de stockage des fichiers récupérés (optionnel : par défaut le répertoire de lancement du client)

Une fois connecté au serveur en TCP, il dispose d'un ensemble de commandes via l'entrée standard dans un petit langage de script qui devra comprendre au moins les commandes suivantes :
  • ls : affichage du contenu du répertoire courant sur le serveur (un fichier/répertoire par ligne avec ses détails)
  • get file : demande de téléchargement du fichier file
  • current : affichage des téléchargements en cours et leur état (pourcentage), chaque téléchargement étant identifié par un entier
  • kill num : interrompt le téléchargement dont l'entier est spécifié

Téléchargement de fichier unicast : get

Lorsqu'un client envoie la commande get file sur la connexion TCP avec le serveur, cela initie un téléchargement du fichier file en UDP, depuis le serveur vers le client. Pour ce faire, le client devra communiquer au serveur (dans le cadre de sa commande get) un numéro de port UDP, sur lequel il s'attend à recevoir les différents tronçons du fichier demandé (l'adresse IP devra être la même que celle de la connexion TCP). Le serveur pourra répondre au client, sur la connection TCP, quelques informations concernant le fichier, comme sa taille, mais pas les données du fichier, qui elles devront transiter en UDP.

UDP n'étant pas fiable, des mécanismes devront être mis en place pour assurer que tous les tronçons du fichier sont bien récupérés par le client de sorte à garantir l'intégrité du fichier reconstitué. Ce mécanisme doit impliquer exclusivement des échanges UDP entre le client et le serveur, sans rien solliciter par TCP.

Diffusion de fichier en multicast : mput

Une autre fonctionalité offerte par MuFiT consiste en la diffusion d'un fichier depuis le serveur vers tous les clients actuellement connectés au serveur. Dans ce cas, c'est à l'initiative du serveur qu'une diffusion de tous les tronçons d'un fichier va être initiée à destination d'une adresse et d'un port de multicast sur lequel chaque client doit écouter. Une réflexion doit être menée pour savoir comment choisir de ce numéro de port UDP multicast (choix arbitraire préalable, imposé par le serveur, négocié avec les clients...). La connexion TCP peut être utilisée pour notifier aux clients des informations sur le téléchargement, comme le nom du fichier ou sa taille.

Attention: dans le cadre de l'utilisation du multicast dans les salles de TP de l'université, il ne faut pas utiliser des adresses dans la plage 224.0.0.0 - 224.0.0.255 qui sont normalement utilisées pour les annonces et le routage multicast. Vous pouvez regarder pour plus de détail l'URL http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xml#multicast-addresses-13 Dans le cadre de votre projet, vous vous limiterez à l'utilisation des adresses dans la plage 239.252.0.0 - 239.255.255.255. Par ailleurs, ne tentez pas de changer le TTL qui doit être à 1 par défaut.

UDP n'étant pas plus fiable en diffusion qu'en unicast, certains tronçons risquent d'être perdus sur certains clients: deux approches peuvent alors être adoptées.
  • Approche 1 - L'approche simple consiste alors à demander au serveur de renvoyer le ou les tronçons manquants.
  • Approche 2 - Une approche plus respectueuse des ressources du serveur consiste à solliciter en priorité les autres clients, qui ont probablement reçus les tronçons et qui pourraient les renvoyer au client.

L'essentiel d'abbord, le reste après

Les commandes du serveur (users, current, kill et mput) et du client (ls, get, current et kill) devront d'aboord être réalisées de manière basique : approche simple et fonctionnelle, noms de fichiers supportés en ASCII, Approche 1 pour la récupération des tronçons manquants en diffusion multicast... Cette implémentation de base est un prérequis à tout autre développement, et pourra donner lieu à une évaluation de 10-12/20 environ.

C'est seulement une fois ces fonctionnalités basiques réalisées et testées que l'on pourra s'intéresser aux amélioration suivantes :
  • du confort d'utilisation. Par exemple, prendre en compte les noms de fichier supportés en UTF-8. Ou encore, proposer sur le serveur non plus un simple répertoire contenant les fichiers servis, mais toute une arborescence. Symétriquement, on souhaite offrir une commande cd dir sur le client qui permette de changer de répertoire courant sur l'arborescence du serveur (sans jamais pouvoir remonter "au dessus" du répertoire servi). De même, sur le client, tous les fichiers sont enregistrés sous le répertoire directory, mais en respectant l'arborescence du serveur. Par exemple, si l'on télécharge le fichier /java/javadoc/index.html sur le serveur et que le client est lancé sous ~/tmp, le fichier est créé à l'emplacement ~/tmp/java/javadoc/index.html (il faudra créer les répertoires intermédiaires si nécessaire).
  • de la mise à disposition des données collectées. Par exemple, la commande stats peut être ajoutée au serveur : elle demande l'affichage des statistiques de téléchargement (données transférées totales, par client, par fichier, par date). De plus, ces données peuvent être rendues persistantes entre deux exécutions du serveur.
  • des performances ou subtilités du protocole de récupération des paquets manquants dans le cas de la diffusion multicast (Approche 2).

Consignes de rendu

Le projet est à réaliser en binôme. En cas d'effectif impair, un seul groupe pourra comporter 3 personnes (pour lequel on sera plus exigeant).

Les arguments et commandes indiqués doivent être respectés scrupuleusement, les programmes rendus étant susceptibles d'être testés automatiquement par des scripts.

Les sources doivent être claires, commentées, organisées en paquetages et le découpage en classes doit être judicieux. Les sources ne peuvent dépendre que de l'API standard du JDK (paquetage java). La copie de code depuis une source externe ou entre des binômes différents n'est pas autorisée.

Un rapport au format PDF d'une dizaine de pages devra être inclus. Il décrira d'une part les choix protocolaires de communication, d'échange de commandes et de données entre les clients et le serveur, et d'autre part les choix d'architecture et d'implantation logicielle. Il précisera les difficultés rencontrées ainsi que les éventuelles limitations, bugs et améliorations.

Vous devez constituer votre binôme et le faire connaître par mail auprès de etienne.duris[at]univ-mlv.fr au plus tard le mardi 12 mars 2013.

Le projet sera à rendre sous forme d'archive zip ne contenant que le minimum (tout ce qui peut être généré doit être supprimé: penser à faire un ant clean avant de générer l'archive) au plus tard le 16 avril 2013. Le contenu de l'archive sera organisé avec les sous-répertoires suivants:
  • un répertoire src contenant les sources du projet;
  • un répertoire docs contenant le rapport au format PDF;
  • un répertoire classes vide dans l'archive et qui contiendra les classes une fois compilées
  • un jar exécutable MuFiTServer.jar qui fonctionne avec java -jar MuFiTServer.jar et donc qui possède un fichier manifest adequat;
  • un jar exécutable MuFiTClient.jar qui fonctionne avec java -jar MuFiTClient.jar et donc qui possède un fichier manifest adequat;
  • un build.xml qui permet de
    • compiler les sources (target compile)
    • créer le jar exécutable (target jar)
    • générer la javadoc dans docs/doc (target javadoc)
    • nettoyer le projet pour qu'il ne reste plus que les éléments demandés (target clean)

Cette archive Zip (attention à l'encodage) aura comme nom Nom1Nom2_MuFiT.zip, où les noms sont ceux des membres du binôme par ordre alphabétique. L'extraction de cette archive devra créer un répertoire de nom Nom1Nom2_MuFiT pour contenir tous les éléments demandés ci-dessus.

Les modalités de rendu (par mail ou via une plateforme de dépôt) seront précisées ici ultérieurement.

Pour rendre votre projet (au plus tard le 16/04/2013), vous devez utiliser la plateforme http://elearning.univ-mlv.fr pour déposer l'unique fichier Nom1Nom2_MuFiT.zip constitué comme spécifié ci-dessus. Jusqu'à la date limite, vous avez la possibilité de modifier ce fichier.

Soutenances

Une soutenance (d'un 1/4 d'heure par binôme) sera organisée le vendredi 19 avril 2013 où vous devrez utiliser l'archive zip rendue et présenter une démonstration que vous aurez préparée et testée dans les salles de TP de l'université.