:: Enseignements :: ESIPE :: E4INFO :: 2013-2014 :: Applications réseaux ::
[LOGO]

Serveur UDP, Tolérance aux pertes


Exercice 1 - Longue Somme de Long

On souhaite mettre en place une sorte de calculette permettant à un client de demander à un serveur le résultat de la somme de plusieurs nombres qui sont des entiers long (sur 8 octets).

Le "protocole" convenu établit que pour cela, le client doit envoyer chaque opérande, un par un, big endian. Le résultat de la somme totale sera renvoyé par le serveur à la fin de la réception des opérandes, qui est signalée par la première opérande nulle (i.e. 0) reçue du client.

Le fichier ClientLongSumDummy.java contient un client trés simple qui envoie succéssivement tous les long d'une liste et attend la réponse du serveur avec un timeout d'une seconde. Vous pouvez le lancer en donant en argument l'adresse et le port du serveur:
$java ClientLongSumDummy localhost 7777

Exercice 2 - Meilleure longue Somme de Long

Pour prendre en compte la perte des paquets et le changement d'ordre, on adopte un protocole un peu plus évolué. Le client veut faire la somme de n longs que si numérotés de 0 à n-1. Il envoie chaque opérande dans un paquet de la forme [INT|INT|LONG] (toujours en big endian). Le premier INT est le nombre total d'opérandes (i.e. n). Le second INT est la position de l'opérande (entre 0 et n-1). Le troisième LONG est la valeur de l'opérande. Pour signaler qu'un paquet a été recu, le serveur renvoie au client un paquet ACK contenant un seul INT (en BigEndian) qui correspond à la position de l'opérande recue. Le serveur attend les opérandes dans l'ordre. Il attend de recevoir d'abord l'opérande à la position 0, puis l'opérande à la position 1, etc ... S'il a recu toutes les opérandes jusqu'à l'opérande de position 3 et qu'il reçoit l'opérande 5, il ignore le paquet. S'il reçoit à nouveau l'opérande 2, il renvoie un ACK pour l'opérande 2. Une fois que toutes les opérandes ont été reçues, le serveur renvoie en plus du paquet ACK, un paquet content un LONG (en big endian) correspondant à la somme de toutes les opérandes.

Un client veut par exemple faire la somme de 5 et 7. Il enverra tout d'abord le paquet [2|0|5]. Quand le serveur recoit, le paquet il renverra le paquet [0] (4 octets). A la reception de cee paquet le client envoie le paquet [2|1|7]. Le serveur renvoie deux paquets: [1] (4 octets) et la somme [12] (8 octets). Si le client ne reçoit pas la réponse du serveur, il renvoie son paquet.

Récupérez le serveur ServerLongSum.jar qui implémente ce protocole et lancez le
$ java -jar ServerLongSum.jar 7777

Ecrivez un client ClientLongSum pour ce protocole et vérifiez qu'il fonctionne même quand vous passez par UDPProxy.

Exercice 3 - Encore Meilleure Longue Somme de Long

Dans une version encore plus évoluée du protocole, le serveur n'est pas obligé de recevoir les paquets dans l'ordre. Récupérez le serveur ServerLongSumSmart.jar qui implémente ce protocole et lancez le
$ java -jar ServerLongSumSmart.jar 7777

Réalisé un client ClientLongSumSmart plus évolué qui a deux threads. Un thread envoie les paquets et l'autre qui reçoit les accusés de réceptions. Le thread qui reçoit mémorise les numéros des paquets reçus par le serveur dans un BitSet qui sera partagé avec le thread qui envoie. Le thread qui envoie utilise une DelayQueue pour gérer les paquets. Une DelayQueue est un structure permettant de mettre des objets en donnant un délai avant qu'ils ne soit autorisés à être repris dans la queue. Allez lire la javadoc sur cette classe, vous verrez que les objets que l'on met dans la DelayQueue doivent implémenter l'interface Delayed. La classse DelayedData.java vous donne un point de départ. Le principe du thread qui fait les envois est le suivant: il remplit la queue avec tous les paquets. Ensuite il prend un paquet de la queue (take) puis il vérifie si l'accusé de réception a été reçu. Si c'est le cas, il n'a rien faire et il recommence à prendre des paquets dans la queue. Si l'accusé de réception n'a pas été reçu, il envoie le paquet correspondant et il rajoute le paquet avec un délai égale au temps d'attente souhaité.