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

Clients TCP simples


Le principe de TCP est de disposer d'une connexion qui offre une communication bi-directionnelle sous la forme de deux flux. Tant que ces flux ne sont pas "fermés", rien ne permet de savoir, a priori, si on a reçu l'intégralité de ce qui a été émis par l'interlocuteur ou s'il reste des données à reçevoir: c'est la "segmentation". Il faut donc, quelque soit le principe ou le protocole retenu, se donner les moyens de savoir si il reste des choses à lire ou pas.
Une technique basique consiste à attendre que le flux de lecture soit fermé pour considérer qu'il n'y a plus rien à lire!
Une autre consiste à utiliser un protocole qui décrit précisément la nature et la taille des données attendues.
Il est aussi possible de détecter dans les informations qu'on reçoit des données "utiles" identifiant la fin de la réponse (comme une fin de ligne par exemple)...

Exercice 1 - Fermez la porte en sortant

On cherche a réaliser un client TCP très simple. Le protocole est le suivant. Le client établit la connexion avec le serveur, puis écrit une chaîne en UTF-8 à destination du serveur et ferme la connection en écriture. Ensuite il lit sur la connexion une chaîne de caractères en UTF-8 dont la fin est signalée par la fermeture de la connexion en lecture.

  1. En partant du fichier ClientEOS.java, écrivez la fonction getFixedSizeResponse qui prend en paramètre la chaîne de caractères à envoyer, l'adresse du serveur et la taille du buffer de réception.
    Si la réponse du serveur dépasse la taille du buffer, on ignore la fin de la réponse.
  2. Ecrivez ensuite la fonction getUnboundedResponse qui doit lire la réponse quelque soit la taille de la chaîne de caractères renvoyée par le serveur.

Exercice 2 - Le protocole, y'a que ça de vrai

Le client précédent a deux inconvénients majeurs: il n'est pas très efficace car demande de manipuler plusieurs fois les données reçues pour reconstituer la réponse, et surtout il ne permet pas de réutiliser la connexion pour une deuxième requête. On va donc maintenant écrire un client qui envoit et reçoit des informations dont le format est précisé par un protocole.

Le but de l'exercice est de réaliser un client qui interroge un serveur devant réaliser la somme d'une liste d'entiers long en suivant le protocole TCP suivant:
  1. le client se connecte au serveur
  2. le client envoie un INT (en big endian) donnant le nombre d'opérandes de l'opération à réaliser, puis chacun des opérandes qui sont des LONG en big endian;
  3. le client lit ensuite la réponse du serveur qui est un LONG correspondant à la somme des opérandes.
  4. le serveur ne ferme pas la connection qui peut donc être utilisée pour faire une autre somme en repartant à l'étape 2.

En partant du fichier ClientLongSum.java, vous devez réaliser un client qui prend en paramètre l'adresse et le port du serveur. Il se lancera par exemple avec:
java fr.upem.net.tcp.ClientLongSum localhost 7777
La méthode requestSumForList(SocketChannel sc, List<Long> list) de votre client doit envoyer la liste d'opérandes au serveur en respectant le protocole, puis lire la réponse du serveur et la renvoyer.
Si le serveur ferme la connection avant d'avoir fini l'échange, votre client affichera le message:
Connection with server lost.
et quittera.

Vous pouvez tester votre client en lancant le serveur ServerLongSum.jar comme suit:
java -jar ServerLongSum.jar 7777

Pour tester le cas où le serveur ferme la connection de manière imprévue, vous lancerez le serveur avec l'option -bug qui introduit une probabilité que le serveur ferme la connection.
java -jar ServerLongSum -bug 7777

Exercice 3 - Bout à bout

Le même genre de protocole peut être mis en place pour échanger des chaînes de caractères.

Le but de cet exercice est de réaliser un client qui se connnecte à un serveur de concatenation de chaînes avec le protocole TCP suivant:
  • le client envoie un INT (en big endian) donnant le nombre de chaînes de caractères, puis envoie chacune de ces chaînes encodée par un INT (pour la taille en nombre d'octets de la chaîne encodée en UTF-8) suivi des octets représentant la chaîne en UTF-8.
  • le serveur répond avec une seule chaîne, représentée sous le même format, correspondant à la concatenation de toutes les chaînes, séparées par des virgules.

Vous réaliserez un client ClientConcatenation.java qui prend en paramètre l'adresse et le port du serveur. Il se lancera par exemple avec:
java upem.net.tcp.ClientConcatenation localhost 7777
Votre client va lire des chaînes au clavier jusqu'à ce qu'il lise une chaîne vide. Il enverra ensuite ces chaînes (sans la chaîne vide) au serveur en respectant le protocole et affichera la réponse du serveur.
Si le serveur ferme la connection avant d'avoir envoyé la réponse, votre client affichera le message:
Connection with server lost.
et quittera.

Vous pouvez tester votre client en lancant le serveur ServerConcatenation.jar comme suit:
java -jar ServerConcatenation 7777
Le serveur écoute sur le port 7777.