CSC 4509 – Algorithmique et communications des applications réparties

Portail informatique

Communication multiclient et multithread

  • Communication entre processus avec l'usage de threads

Communication multiclient et multithread

Préparation

Pour ce TP nous utiliserons le projet csc4509-5-multithreads déjà importé sur votre IDE depuis le premier TP.

En plus des paquetages auxquels vous êtes maintenant habitués, cette archive contient un paquetage "interfaceGraphique" qui contient quelques classes pour créer un une interface graphique avec SWING. Vous n'avez pas besoin de lire ou comprendre ces classes.

Cette interface servira pour la partie client de l'application à développer pour ce TP (un tchat multiclient, monoserveur). Pour vous en servir, vous avez juste besoin de savoir deux choses:

  • Elle utilise un objet "worker" de la classe "FullDuplexMsgWorker" (le worker qui reliera le client au serveur).
  • Pour lui demander d'afficher une ligne de texte (String) dans la fenêtre de tchat, il faudra utiliser la méthode "interfaceGraphique.getTexte().ecrireNouvelleLigne(ligne)", où "interfaceGraphique" est l'objet de la classe InterfaceGraphique construit dans le "main" du fichier "MainMsgNioClient" (qui vous est partiellement donné).

Écriture du serveur

Ecrivez dans la classe "MainSelectMsgServer" un serveur multiclient en utilisant la classe Selector de JAVA NIO. Ce serveur est très similaire à celui du TP4, mais à la place d'afficher les messages qu'il reçoit, il doit les renvoyer à tous les clients connectés, sauf l'émetteur du message. Donc n'hésitez à vous inspirer beaucoup du serveur du TP4.

Écriture du client

Le client se trouve placé entre deux actions bloquantes:

  • d'un coté il doit lire les lignes que saisit l'utilisateur pour les envoyer au serveur.
  • de l'autre il doit lire les messages que lui envoie le serveur pour les afficher dans la fenêtre de tchat.

Pour résoudre ce double blocage, le client va être divisé en deux threads qui bloqueront chacun de leur coté.

  • Le premier thread est déjà fourni. C'est celui créé par SWING. Il prendra en charge les messages tapés par les utilisateurs, et utilisera un "worker" (instance de "FullDuplexMsgWorker") pour les transmettre au serveur.
  • Le deuxième est à écrire de toute pièce. Il devra utiliser l'objet "interfaceGraphique" de la classe "InterfaceGraphique" que vous trouverez dans le "main" du fichier "MainMsgNioClient" partiellement fourni.

Donc pour le client il vous reste deux étapes à réaliser:

  • Créer et écrire la classe ThreadClient qui gérera le second thread du client.
  • Finir d'écrire le "main" du fichier "MainMsgNioClient".

(défi) Section critique et exclusion mutuelle

Si vous êtes arrivé jusqu'au bout de l'écriture de vos programmes, voici un petit défi supplémentaire

La solution que l'on vous a demandée, crée deux threads qui se partagent la même ressource: le panel où les lignes de la conversation du tchat apparait.

La méthode qui utilise cette resource est "ecrireNouvelleLigne" (ligne 29 de la classe Texte). Elle peut être appelée silmultanément par le thread du client que vous avez écrit, et par le thread de SWING (appel dans la classe CallBack, ligne 46).

Donc, le Vector "leTexte" peut être modifié simultanément par deux threads et être incohérent. Il faut une exclusion mutuelle pour gérér l'accès à ce Vector. Il existe plusieurs moyens de créer des exclusions mutuelles en JAVA. Certaines classes permettent des opérations très précises (Lock, Semaphore, ...), mais pour notre exemple l'usage d'une section synchronisée suffit.

Après avoir lu une explication sur les verroux par le mot clef "synchronized", modifiez la méthode "ecrireNouvelleLigne" de la classe Texte pour le problème d'accès concurrent au Vector "leTexte" soit résolu.

Nota Bene: lorsqu'on utilise SWING avec ses bonnes pratiques, le problème expliqué ci dessus ne se pose pas. Dans la solution qui vous sera proposée sur moodle, vous verrez une autre façon d'écrire le thread client qui évite l'accès concurrent au Vector "leTexte"

un peu plus loin

Si vous avez fini la question précédente, vous pouvez modifier votre serveur pour obtenir une architecture multi-client et multi-serveur. Jusqu'à présent l'achitechture utilisée est une étoile: il y a un seul serveur au milieu de N clients. Il va falloir modifier votre serveur pour qu'à son lancement il puisse se connecter à un autre serveur qui tourne déjà. Le réseau de serveurs et de clients va donc former un arbre

Modifiez votre serveur pour qu'il puisse gérer soit 1 soit 3 arguments. Dans le cas où il reçoit 3 arguments, voici leurs usages:

  • argv[0] : le port occupé par votre serveur.
  • argv[1] : le nom d'une machine où tourne un exemplaire de votre serveur auquel votre serveur va se connecter
  • argv[2] : le port du serveur auquel votre serveur va se connecter

Modifiez votre serveur pour que tous les messages qu'il reçoit des clients soient aussi transmis au serveur auquel il s'est connecté, et que tous les messages qu'il reçoit de ce serveur, soient transmis à tous les clients.

 

 

 


$Date: 2017-12-07 14:00:48 +0200 (mer. 12 avril 2017) $