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

Serveur TCP concurrent avec 2 sens de communications indépendants


On souhaite réaliser un client et un serveur très simples pour implémenter un service de messagerie instantanée de groupe implémentée en TCP.
Le principe est très simple: chaque client se fait connaitre en établissant une connexion TCP avec le serveur, et en envoyant une 1ère chaîne de caractères faisant office de "pseudo" (identifiant) pour ce client.
Ensuite, le serveur fait en sorte que chaque chaîne de caractères reçue d'un client soit préfixée par son pseudo avant d'être envoyée à tous les clients.
Chaque chaîne de caractères sera transmise sous la forme d'un INT (4 octets en Big Endian) représentant le nombre d'octets qui suivent, ces octets correspondant à l'encodage en UTF-8 de la chaîne à transmettre. Par exemple, la chaîne "ABCD€" sera transmise par les 7 octets suivants:
0 0 0 7 65 66 67 68 226 130 172
0 0 0 7 est la valeur entière 7 en Big Endian sur 4 octets et où les 7 octets suivants codent en UTF-8 les 5 caractères de la chaîne (226 130 172 encodent le caractère '€').

Exercice 1 - Client de messagerie instantanée en TCP

On commence par écrire un client ChatClient qui, après avoir établi une connexion avec le serveur spécifié par son nom et son numéro de port sur la ligne de commande, doit simultanément et dans deux threads différentes:
  • lire les chaînes de caractères saisies par l'utilisateur sur l'entrée standard et les envoyer au serveur dans le format spécifié ci-dessus;
  • afficher à l'écran chaque chaîne reçue depuis le serveur dans le même format.
Lorsque le serveur ferme le flot de lecture de l'entrée standard (par Crtl-D par exemple), cela entraine la fermeture de la connexion avec le serveur et l'arrêt du client.

Exercice 2 - Serveur de messagerie instantanée en TCP

On veut maintenant écrire le serveur ChatServer. Celui-ci se démarre en acceptant sur la ligne de commande le numéro de port d'écoute des clients, et le nombre maximum de clients qui peuvent être servis simultanément. Vous vous inspirerez de l'architecture Fixed Prestart Concurrent Serveur vue au TD précédent, mais en considérant que chaque client devra pouvoir être servi par 2 threads:
  • l'une, de lecture, qui écoute les chaînes en provenance du client, qui peuvent arriver au serveur à tout moment. Lorsque la chaîne "blabla" est reçue du client c1, la thread de lecture de c1 se charge d'ajouter, dans la file d'attente de chaque client le message "c1 : blabla";
  • l'autre, d'écriture, est en charge d'envoyer au client toutes les chaînes reçues en provenances des autres clients connectés. Cette thread prendra chaque message de la file d'attente du client c1 pour les envoyer au client c1.

  • Développer une première version simple du serveur ChatServer qui se démarre en passant sur la ligne de commande le port d'écoute du serveur ainsi que le nombre de clients acceptés simultanéments.
    java fr.upem.net.tcp.ChatServer 7777 10
    
    Vous testerez cette version avec le client développé à l'exercice précédent.
  • Recopier cette classe dans une nouvelle classe StoppableChatServer qui supporte, dans la fenêtre de lancement, la lecture d'une commande "shutdown" sur l'entrée standard. Cette commande aura pour effet d'arrêter le serveur en fermant proprement toutes les connexions actives avec des clients.
  • Recopier cette classe dans une nouvelle classe StoppableTimeableChatServer qui supporte, en plus, de déconnecter automatiquement les clients inactifs (qui n'ont rien envoyé depuis un certain temps).