Echo non-bloquantLe but de cet exercice est de mettre en application les concepts vus dans le cours sur UDP en mode non-bloquant. On cherche à réaliser un serveur pour le protocole Echo.
EchoEcho, le serveur renvoie aux clients les paquets qu'il reçoit à l'identique. On supposera que les paquets ne dépassent pas 1024 octets.
En partant du fichier ServerEcho.java, écrivez un tel serveur ServerEcho qui prend en argument son port d'écoute.
Attention rappelez-vous que même si le sélecteur renvoie une clé de sélection en disant qu'une réception ou qu'un envoi de paquet est possible, il n'y a aucune garantie que la réception ou l'envoi soit effectivement réalisé lors de l'appel à datagramChannel.receive() ou datagramChannel.send().
datagramChannel.receive() : elle est null si aucun paquet n'a été reçu.buffer.hasRemaining() après le datagramChannel.send(buffer, sender) : si l'envoi n'a pas eu lieu, la zone de travail de buffer est inchangée.Si l'envoi ou la réception n'ont pas eu lieu, il faut que votre code interroge à nouveau le sélecteur et attende qu'il repropose la clé pour tenter une nouvelle fois.
Il est très rare que le sélecteur propose une clé sans que l'envoi ou la réception ne soit possible. Vous ne pourrez donc pas tester votre code dans ces cas et il vous faudra le prévoir par vous-même en regardant précisément le comportement de votre code en cas d'échec de l'envoi ou de la réception.
Pour tester votre serveur, vous pouvez utiliser le client NetcatUDP.jar. Ce client envoie des paquets correspondants à chaque ligne tapée au clavier (encodée en UTF8) et affiche la chaîne correspondant au paquet reçu (décodée en UTF8).
$ java fr.uge.net.udp.nonblocking.ServerEcho 4545 $ java -jar NetcatUDP.jar localhost 4545 UTF8 toto String: toto
Nous allons maintenant légèrement modifier le protocole Echo pour obtenir le protocole EchoPlus.
On supposera que les paquets ne dépassent pas 1024 octets.
Par exemple, en recevant le paquet de 7 octets suivant :
+----------------------+
| FF 0A 11 1F FF 00 01 |
+----------------------+
le serveur renverra au client le paquet :
+----------------------+
| 00 0B 12 20 00 01 02 |
+----------------------+
Écrivez une classe serveur ServerEchoPlus qui implémente en mode non-bloquant un serveur pour le protocole EchoPlus.
Vous pourrez partir du code de votre classe ServerEcho.
Vérifiez bien que votre code est correct dans le cas où datagramChannel.send() ou datagramChannel.receive() n'effectuent pas l'envoi ou la réception malgré le fait qu'ils aient pu être sélectionné.
Pour tester votre serveur, vous pouvez utiliser le client NetcatUDP.jar.
$ java fr.uge.net.udp.nonblocking.ServerEchoPlus 4545 $ java -jar NetcatUDP.jar localhost 4545 UTF8 toto Received 4 bytes from /127.0.0.1:4545 String: upup
Echo multi-port NIO
Dans cet exercice, nous cherchons à écrire un serveur Echo ServerEchoMultiPort qui prend en argument
une plage de ports. Si vous lancez votre serveur avec:
java fr.uge.udp.nonblocking.ServerEchoMultiPort 7000 7100votre serveur se comportera comme un serveur Echo sur chacun des ports de la plage [7000 .. 7100] (inclus).
Jusqu'à présent, le sélecteur ne surveillait qu'un seul DatagramChannel. Dans cet exercice, il faudra créer un DatagramChannel pour chaque port de la plage et tous les enregistrer auprès du sélecteur.
Il faudra stocker pour chaque SelectionKey un ByteBuffer et une InetSocketAddress. Pour stocker ces deux informations vous créerez une classe interne Context.
Pour associer à chaque SelectionKey un objet Context, on pourrait utiliser une Map<SelectionKey,Context>. Cependant la classe SelectionKey permet déjà d'attacher un objet quelconque à la clé. La méthode selectionKey.attach(Object obj) permet de stocker un objet dans la clé et la méthode selectionKey.attach() permet récupérer cet objet.
Remarquez que l'on peut attacher un objet à la création de la clé (c'est-à-dire au moment de l'enregistrement de la DatagramChannel auprès du sélecteur):
dc.register(selector, SelectionKey.OP_READ, new Context());
Vous pouvez tester votre serveur en lancant le client ClientTestEchoMultiPort.jar comme suit:
java -jar ClientTestEchoMultiPort.jar localhost 7000 7100Ce test simule 10 clients qui envoient 100 paquets sur la plage de ports entre 7000 et 7100. Il vérifie que tous les paquets réponses sont bien reçus. Si tout se passe bien, vous devez voir:
No error found.
Dans cet exercice, vous devez implémenter un serveur UDP en mode non-bloquant, qui implémente le protocole très simple décrit ci-après.
Dans le protocole EchoRepeat, le client envoie un paquet au format suivant :
int en Big Endian représentant le nombre strictement positif de répétitions (rep),Par exemple, en recevant le paquet de 7 octets suivant :
+----------------------+
| 00 00 00 02 FF FF FF |
+----------------------+
qui correspond à un rep de 2 et un content de 3 octets valant tous les 3 FF.
Le serveur enverra 2 fois au client le paquet :
+----------+
| FF FF FF |
+----------+
À partir du squelette de la classe
ServerEchoRepeat.java,
écrivez un serveur en mode non-bloquant pour ce protocole.
Attention : si le selecteur donne un hint pour write/read, vous ne pouvez envoyer/recevoir qu'un seul packet.
Avant d'en envoyer/recevoir un autre, il vous faudra faire un autre appel à select pour être sûr d'en
avoir le droit.
Pour tester votre serveur, vous pouvez utiliser le client ClientEchoRepeat.jar. Ce client prend en arguments l'adresse et le port du serveur. Il demande d'entrer au clavier le nombre de répétitions souhaitées puis une chaîne de caractères qui (une fois encodées en UTF8 par le client) correspondra au content du paquet envoyé.
Par exemple, si votre serveur est lancé sur le port 7777 :
$java fr.uge.net.udp.nonblocking.ServerEchoRepeat 7777
Vous pouvez le tester depuis un autre terminal (en gras, ce que l'utilisateur saisit sur l'entrée standard) :
$java -jar ClientEchoRepeat.jar localhost 7777 Number of repetitions: 3 Content: abc€ Received 6 bytes from server Content: abc€ Received 6 bytes from server Content: abc€ Received 6 bytes from server Content: abc€