:: Enseignements :: Master :: M1 :: 2014-2015 :: Programmation d'applications réseaux ::
[LOGO]

Multicast, UDP non-bloquant


Exercice 1 - Chat Multicast

Le but du l'exercice est d'écrire une application de chat en utilisant une adresse multicast commune à tous les clients. Un client est lancé avec un pseudo, une adresse multicast (IP+port) et une interface réseau.
$ java MulticastChat Charlie 239.252.0.100 7777 eth0

Si vous êtes sur votre portable, vous ne pourrez pas communiquer avec les autres clients. Vous pouvez tester en local en lançant plusieurs clients.
$ java MulticastChat Alice 239.252.0.100 7777 lo0
$ java MulticastChat Bob 239.252.0.100 7777 lo0

Les paquets envoyés et recus sur cette adresse contiendront un pseudo et un message. Le format est le suivant:
  1. un INT donnant la taille du pseudo
  2. le pseudo encodé en UTF-8
  3. le message encodé en UTF-8
L'ensemble du paquet ne pourra pas dépaser la taille de 512 octets.
+--------------+------------------+--------------------------+
| taillePseudo |   Pseudo UTF-8   |       Message UTF-8      |
+--------------+------------------+--------------------------+
       

Attention: dans le cadre de l'utilisation du multicast dans les salles de TP de l'université, il ne faut pas utiliser n'importe quelle adresse de multicast (certaines sont utilisées pour des annonces ou du routage). Vous pouvez regarder pour plus de détail l'URL http://www.iana.org/assignments/multicast-addresses/multicast-addresses.xml#multicast-addresses-13. Limitez vous à l'utilisation des adresses dans la plage 239.252.0.0 - 239.255.255.255. Par ailleurs, ne changez pas le TTL qui doit être à 1 par défaut.

L'application affichera sur la sortie standard tout ce qui est reçu sur ce groupe de multicast à destination de ce port sous la forme "pseudo: message". Il vous faut donc 2 threads.

Le code ci-après vous montre comment configurer une DatagramChannel pour la réception mutlicast. Vous voyez que la configuration demande de préciser l'interface réseau sur laquelle la communication aura lieu.

Exercice 2 - Serveur Echo NIO

En partant du fichier ServerEchoNIOTemplate.java, écrivez un serveur Echo ServerEchoNIO qui prend en argument son port d'écoute. Si votre serveur écoute sur le port 7777, vous pouvez le tester avec nc -u localhost 7777.

Exercice 3 - Serveur Echo multi-port NIO

En partant du fichier ServerEchoNIOTemplate.java, écrivez un serveur Echo ServerEchoNIOMultiPort qui prend en argument une plage de ports. Si vous lancez votre serveur avec:
java upem.net.udp.ServerEchoNIOMultiPort 7000 7100
votre serveur se comportera comme un serveur Echo sur chacun des ports de la plage 7000 .. 7100.

Vous pouvez tester votre serveur en lancant le client ClientMultiPort.jar comme suit:
java -jar ClientEchoMultiPort localhost 7000 7100
Le client envoie 1000 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:
Test passed!

Exercice 4 - Client longue somme de long en non bloquant

Sur la base du protocole de somme de long déjà manipulé dans la planche d'exercices précédente, et rappelé ci-dessous, on souhaite maintenant développer un client qui est capable d'envoyer des séquences de sommes en respectant le protocole mais qui n'utilise qu'une seule thread. Il devra donc utiliser un sélecteur qui sélectionnera la DatagramChannel en écriture lorsqu'il faut envoyer des opérandes (trames OP) ou pour signifier la fermeture de session (trames CLEAN), et qui la sélectionnera en lecture tant qu'il attend un accusé de réception d'opérande (trame ACK), un résultat (trame RES) ou l'accusé de réception d'une fermeture de session (trame ACKCLEAN).

Vous écrirez un client qui utilise le processus d'envoi de ses opérandes par "rafales" (burst) et qui les renvoie tant qu'elles n'ont pas été acquitées.

Vous pourrez tester votre client avec le serveur ServerLongSum.jar et en l'interrogeant à travers le proxy UDP UDPProxy.jar

Pour rappel, chaque paquet débute par un code d'opération codé sur un octet qui vaut:
  • OP = 1 si le paquet contient une opérande envoyée par le client au serveur.
    Dans ce cas, le paquet a le format suivant:
     byte    long       long        long        long
    +---+-----------+-----------+-----------+-----------+
    | 1 | sessionID | idPosOper | totalOper |  opValue  |  // paquet OP
    +---+-----------+-----------+-----------+-----------+
    
    • sessionID est un identifiant de session unique choisi par le client et commun à tous les échanges liés à une somme donnée,
    • idPosOper est la position de cette opérande dans la somme, qui l'identifie (valeur comprise dans l'intervalle [0 .. totalOper-1[)
    • totalOper est le nombre total d'opérandes de cette somme,
    • et enfin opValue est la valeur de l'opérande en question.
  • ACK = 2 si le paquet contient l'accusé de réception envoyé par le serveur en réponse à un paquet OP.
    Dans ce cas, le paquet a le format suivant:
     byte    long       long
    +---+-----------+-----------+
    | 2 | sessionID | idPosOper |  // paquet ACK  
    +---+-----------+-----------+
    
    • sessionID est l'identifiant de session
    • et idPosOper est la position de l'opérande acquittée
  • RES = 3 si le paquet contient la somme de toutes les opérandes. Le serveur envoie un paquet RES en réponse à n'importe quel paquet OP d'un client dès lors qu'il a reçu toutes les opérandes de cette somme (session) -- cet envoi a lieu en plus du paquet ACK acquittant le paquet OP reçu.
    Dans ce cas, le paquet RES a le format suivant:
     byte    long       long
    +---+-----------+-----------+
    | 3 | sessionID |    sum    |  // paquet RES
    +---+-----------+-----------+
    
    • sessionID est l'identifiant de session
    • et sum est la somme de toutes les opérandes de cette session
  • CLEAN = 4 pour les packets envoyés par le client au serveur pour lui signifier que la session ne sera plus utilisée par la suite.
    Dans ce cas, le paquet CLEAN a le format suivant:
     byte    long       
    +---+-----------+
    | 4 | sessionID |     // paquet CLEAN
    +---+-----------+
    
    • sessionID est l'identifiant de session
  • ACKCLEAN = 5 pour un packet envoyé par le serveur en réponse au paquet CLEAN d'un client.
    Dans ce cas, le paquet ACKCLEAN a le format suivant:
     byte    long       
    +---+-----------+
    | 5 | sessionID |     // paquet ACKCLEAN
    +---+-----------+
    
    • sessionID est l'identifiant de session
Note: Tous les enliers long sont transmis en Big Endian.