TD 7

Vendredi 7 mars 2003

Dans ce td nous allons nous intéresser aux sockets utilisant le protocole UDP. Ce protocole n'est pas fiable, il travaille en mode non connecté et respecte les limites des messages. En d'autres termes, les datagrammes émis peuvent être perdus ou dupliqués ; il est possible d'envoyer des données même si personne n'est susceptible de les recevoir et quand les données sont reçues elles le sont dans leur intégralité.

Pour écrire un serveur utilisant UDP, il suffit de créer une prise de type SOCK_DGRAM et l'attacher à une adresse et à un port1 donné au moyen de bind. Le serveur peut alors recevoir des données avec l'appel à la fonction recvfrom2. S'il y a suffisamment de place3 dans le tampon de réception pour stocker les données, on est sûr que la totalité des données a été reçue. Pour envoyer des données il faut utiliser la fonction sendto.

Pour créer un client, il suffit de créer une prise de type SOCK_DGRAM puis lire et écrire avec sendto et recvfrom. Notez bien que les messages transmis ne peuvent pas être de taille arbitrairement grande. Dans toutes les questions veillez à ne pas dépasser une taille de 1024 octets en émission comme en réception.

1  Un serveur UDP

Écrire une fonction establish_udp_server semblable à la fonction establish_concurrent_server: (file_descr -> sockaddr -> string -> unit) -> int -> unit du td précédent, où le premier argument est le descripteur sur lequel il faut écrire, le deuxième est la prise depuis laquelle la connexion a été initiée et le troisième contient ce que le client a écrit.

Lancez un serveur udp qui met en majuscule comme dans le td précédent. Vous testerez votre serveur avec le client écrit dans la question suivante.
(corrigé)

2  Un client UDP

Écrivez un client udp qui se connecte sur votre serveur de la première question, lui envoie ce qui est entré au clavier et affiche ce qu'il reçoit.

Pour être sûr que la réponse vient bien du serveur il est possible d'utiliser une pseudo-connexion en appelant la fonction connect. Contrairement à son utilisation avec TCP, aucune communication n'a lieu, tout est local. La pseudo-connexion assure que seuls les paquets en provenance du serveur peuvent être reçu pendant la pseudo-connexion. Les autres datagrammes sont éliminés.

Une fois qu'une prise UDP est pseudo-connectée il est possible d'utiliser les méthodes read et write comme dans le cas de TCP.

Afin de ne pas bloquer indéfiniment sur un appel à read qui ne recevrait pas de datagramme, il est possible de placer un délai maximum d'attente en lecture au moyen de la fonction système setsockopt_float grâce à l'option SO_RCVTIMEO. En cas de délai expiré l'exception Unix_error(EAGAIN,_,_) est levée.

Pour tester votre programme vous pouvez essayer de contacter un port d'une machine qui n'existe pas.
(corrigé)

3  Un serveur TFTP

On désire créer un serveur de fichiers utilisant le protocole TFTP (Trivial File Transfer Protocol) qui est largement utilisé, dans les réseaux locaux, pour transférer les fichiers de configuration. Nous nous restreignons ici à la lecture de fichiers binaire (mode octet) stockés sur le serveur. Le protocole TFTP utilise le protocole de transport UDP, il faut donc gérer les pertes de datagrammes en renvoyant, un certain nombre de fois les datagrammes non reçus par les clients avant d'échouer. Pour cela, comme dans l'exercice précédent, nous utiliserons pour les prises, l'option SO_RCVTIMEO.

Le protocole TFTP et le format des datagrammes est décrit dans la RFC 1350 (rfc1350.txt). Le scénario standard pour le serveur consiste à attendre les requêtes. Quand une requête de lecture arrive, le serveur crée un nouvelle socket puis émet un premier (numéro 1) datagramme contenant les 512 premiers octets du fichier (ou moins si le fichier est plus petit). Il attend alors l'acquittement du datagramme numéro 1. Quand il l'a reçu, il peut émettre le tronçon suivant de 512 octets avec le numéro 2 et attendre son acquittement, et ainsi de suite. La fin de fichier est détectée quand un datagramme contenant un tronçon de moins de 512 octets est émis. À tout moment un datagramme d'erreur peut arriver ou être envoyer pour terminer le transfert.

Les formats des datagrammes que nous allons traiter sont les suivants : Reportez-vous à la RFC pour avoir plus de détails sur le protocole et le format précis des datagrammes.

Pour tester votre serveur vous pouvez utiliser le client tftp accessible sous ~roussel/bin/tftp. L'exemple suivant demande le transfert du fichier foo en mode binaire depuis le serveur attaché au port 2000 de la machine locale.

Pour vérifier que votre serveur gère bien les pertes vous pouvez, par exemple, simuler dans votre code la perte de certains datagrammes émis et/ou reçus.

shell> ~roussel/bin/tftp localhost 2000
tftp> binary
tftp> get foo
(corrigé)



This document was translated from LATEX by HEVEA and HACHA.