L'objectif de ce TD est de programmer un serveur de transfert de fichier. Cette opération devrait être à 100 % fiable (aucune perte de donnée autorisée). Il existe deux protocoles classiques pour le transfert de données sur Internet TCP permettant un échange fiable et UDP ne comportant aucun mécanisme qui assure la fiabilité de la communication. Comme l'objectif est de construire le protocole "manuellement", nous allons utiliser les sockets java datagrammes qui implémentent  le protocole UDP. Le protocole ftp est un protocole de niveau "application" utilisant les service de transfert de données TCP et ne sera donc pas considéré dans ce TD. Nous nous intéresserons plutôt au protocole TFTP (Trivial File Transfer Protocol) qui nous permettra de découvrir la mise en oeuvre des mécanismes de transfert de fichiers en utilisant un protocole de détection et de correction d'erreur simpliste (Stop and wait). Les paquets sont envoyés un par un. Après l'envoi d'un paquet, un accusé de réception doit être nécessairement reçu avant de procéder à l'envoi du paquet de donnée suivant.

La spécification d'un délai d'attente de la socket est effectuée par l'appel socket.setSOTimeout(d). Où d est le délai en millisecondes. Mettre un délai d = 0 signifie une attente bloquante.

Exercice 1
Il faudra réaliser un serveur de transfert de fichier qui accepte uniquement l'opération de lecture de fichiers, i.e. l'envoi d'un fichier demandé par un client. Afin d'éviter l'interférence entre les messages en provenance de clients différents, un mécanisme local et unilatéral de pseudo-connexion permettant d'établir une communication exclusive entre la socket du serveur et celle du client dont la requête est en cours de traitement, peut être réalisé en utilisant la méthode connect(). Aucun datagram ne pourra être émis ou reçu d'une autre socket. Le protocole TFTP permet d'effectuer les opérations de lecture (get) et d'écriture de fichier (put). Dans notre exemple, nous utiliserons un client TFTP standard, pour cela il convient de programmer l'envoi d'un code signalant une erreur au client dans le cas où le client demande une opération d'écriture. Le format des paquets envoyés par le client ou le serveur est le suivant:

GET:
2 octets code opération (valeur = 1 pour désigner une opération de lecture)
n octets Nom du fichier (nom local au serveur codé en ascii)
1 octet (valeur = 0 pour marquer la fin du nom de fichier)
m octets Mode de transfert (une chaîne de caractère, implémenter uniquement le mode "octet")
1 octet (valeur = 0 pour marquer la fin de la chaîne indiquant le mode de transfert)

PUT
idem, avec code opération = 2 (ne pas implémenter)

DATA
2 octets code opération (valeur = 3 pour désigner un paquet de donnée)
2 octets Numéro de bloc
<= à 512 octets (Données). Les paquets de données envoyés par le serveur sont de 512 octets sauf le dernier qui est de taille <=  512.

ACK
2 octets code opération (valeur = 4 pour désigner un accusé de réception)
2 octets Numéro du bloc dont on accuse réception.

ERROR
2 octets code opération (valeur = 5 pour désigner un message d'erreur de protocole, qui doit intérrompre la communication)
2 octets Numéro d'erreur (valeur = 0 (erreur non définie) ou 1 (fichier non trouvé) ou 2 (Violation du droit d'accès))
n octets Message (précise le type d'erreur intervenue)
1 octet (valeur = 0, marque la fin du message d'erreur)

Choisir un port UDP d'attachement du serveur différent du port par défaut (69 pour tftp).
Le serveur devrait afficher le temps total de l'opération de lecture ainsi que le débit moyen du transfert de données défini par
(taille du fichier / temps total de transfert) en Kilobits par seconde (ou mieux en Mégabits par seconde :-).
Tester avec plusieurs tailles de fichiers allant jusqu'à 1 Mégaoctet.

Vous trouverez ici une implémentation du serveur tftp.

Exercice 2

Provoquer des pertes de paquets (5 à 20 %) et tester la robustesse (est ce que le protocole continue à fonctionner correctement?) et les performances (est ce que le transfert du fichier est aussi rapide?) de votre serveur dans un cas de fonctionnement similaire à un réseau étendu.

Exercice 3

Dans l'exercice 1, le protocole de contrôle de flux implémenté par le serveur est le "stop and wait". Réaliser un serveur qui gère l'envoi d'une "fenêtre" de paquets avant l'arrêt en attente d'un accusé de réception. Tester le fonctionnement avec le client tftp standard. Si ça ne fonctionne pas ou si les performances sont médiocres, implémenter un client capable de gérer la mise en tampon mémoire des paquets de données envoyés par le serveur et d'envoyer les accusés de réception de façon adéquate dans un contexte d'erreur tel que dans l'exercice 2. Quel débit moyen maximal obtenez vous?