Client UDP tolérant aux pertes

Test du proxy UDP

En utilisant le serveur de mise en majuscule ServerUpperCaseUDP.jar et votre client NetcatUDP développé lors de la séance précédente, nous allons introduire artificiellement de l'instabilité entre le client et le serveur en introduisant un proxy ou relai : le client interroge le proxy, qui relaie les demandes au serveur, et les réponses du serveur au proxy sont relayées au client.

En UDP, les paquets peuvent être perdus ou retardés, mais ce comportement se produit rarement sur un réseau local. Le programme UDPProxy.jar va nous permettre de le simuler sur votre machine. ProxyUDP est un proxy UDP qui va perdre un certain pourcentage des paquets et qui peut échanger aléatoirement l'ordre des paquets.

Dans trois consoles (shell) différentes, simultanément visibles à l'écran, exécutez les trois applications suivantes :

$ java -jar ServerUpperCaseUDP.jar 4545 UTF-8  
$ java -jar UDPProxy.jar 7777 localhost 4545 -no-swap
$ java fr.uge.net.udp.NetcatUDP localhost 7777 utf-8
et testez votre client en lui demandant d'envoyer des chaînes successives.

Que se passe-t-il lorsque le proxy décide de jeter un paquet ? Quel est l'impact sur votre client par la suite ?

Première tentative de résilience aux pertes

Dans cet exercice, nous allons modifier NetcatUDP pour essayer de le rendre résistant aux pertes de paquets.

Recopiez votre client NetcatUDP dans une classe ClientUpperCaseUDPTimeout et modifiez-la, dans un premier temps, de manière à afficher "Le serveur n'a pas répondu" si le serveur n'a pas répondu en moins d'une seconde.

Rappel : Le problème est que la méthode receive de DatagramChannel est bloquante et qu'il n'est pas possible de lui fournir un timeout.
Une solution consiste à lancer un thread listener qui fera la lecture sur la DatagramChannel et qui communiquera les chaînes en majuscules reçues au thread principal au moyen d'une BlockingQueue.
Après avoir démarré votre thread d'écoute, vous pourrez accéder aux réponses du serveur en utilisant la méthode poll de la BlockingQueue qui prend en paramètre un délai de timeout.

Testez votre classe ClientUpperCaseUDPTimeout avec le proxy comme dans l'exercice précédent.

Recopiez votre client dans une classe ClientUpperCaseUDPRetry et modifiez-la pour que la requête soit renvoyée si aucune réponse n'est reçue au bout d'une seconde et ce jusqu'à ce qu'une réponse arrive.

Tester votre classe ClientUpperCaseUDPRetry avec le proxy.

Des milliers de lignes à mettre en majuscules ?

Dans cet exercice, on cherche à utiliser un serveur ServerUpperCaseUDP pour mettre en majuscules toutes les lignes d'un fichier.
Le protocole, dans l'état actuel, ne permet pas de réaliser un tel client. Le but l'exercice est simplement de constater ce qui se passe.

Plus précisément, le programme ClientUpperCaseUDPFile prend en paramètres sur la ligne de commande :

Le main de ClientUpperCaseUDPFile doit :
  1. récupérer toutes les lignes du fichier in-filename ouvert avec le jeu de caractères UTF-8 et les stocker dans une liste ;
  2. mettre chaque ligne en majuscules en utilisant le serveur ServerUpperCaseUDP dont l'adresse est donnée en paramètre ;
    On procédera comme dans ClientUpperCaseUDPRetry : pour chaque ligne, une requête est envoyée au serveur. Si aucune réponse n'arrive avant timeout millisecondes, la requête est renvoyée, et ce, jusqu'à ce qu'une réponse du serveur soit reçue. Toutes les chaînes de caractères correspondant (en UTF-8) aux réponses sont stockées dans une liste.
  3. Toutes les lignes contenues dans la liste sont écrites dans le jeu de caractères UTF-8 dans le fichier out-filename.

En partant du squelette ClientUpperCaseUDPFile.java, écrivez la classe demandée.

Testez votre programme comme précédemment, à travers le Proxy UDP et avec le fichier in.txt comme ci-dessous :

        $ java -jar ServerUpperCaseUDP.jar 4545 UTF-8
    
        $ java -jar UDPProxy.jar 7777 localhost 4545 -no-swap
    
        $ java fr.uge.net.udp.ClientUpperCaseUDPFile in.txt out.txt 300 localhost 7777
    

Observez le fichier out.txt. Expliquez la présence de lignes dupliquées en sachant qu'avec les paramètres par défaut du proxy, un paquet met 300ms pour aller du client au serveur ou du serveur au client.