:: Enseignements :: Master :: Master TTT :: 2012-2013 :: Programmation réseau en Java ::
[LOGO]

TCP et concurrence


Ce TD est une introduction à la programmation de serveurs TCP concurrents en Java. Le premier exercice est une adaptation d'un serveur d'un modèle itératif vers un modèle concurrent. Le deuxième exercice nous invite à réaliser un serveur servant de médiateur entre des clients producteurs et consommateurs d'éléments ; il nous incite à utiliser les mécanismes d'attente passive et de signalisation. Le troisième exercice consiste à implanter un proxy TCP : il s'agit de supporter un scénario de communication asynchrone et ainsi d'utiliser une thread pour chaque direction de transfert.

Exercice 1 - Tortureur de lignes concurrent

Exercice 2 - Un serveur médiateur

On souhaite transmettre des objets de producteurs vers des consommateurs. Une possibilité est de créer un serveur consommateur recevant des éléments de clients producteurs. Mais comment faire si nous avons plusieurs consommateurs qui se partagent les objets produits ? Nous proposons de créer un serveur médiateur se chargeant de relayer les éléments des producteurs vers les consommateurs. Son fonctionnement peut ainsi être décrit :
  • Un producteur se connecte en tant que client et peut laisser un élément avec la commande "PUT element" (l'élément est une chaîne de caractères).
  • Un consommateur se connecte également en tant que client et peut récupérer l'élément laissé avec "TAKE" (le serveur retourne une ligne avec l'élément).
Dans un premier temps, le serveur ne peut stocker qu'un élément en cours de transit (dans un champ String par exemple).

Malheureusement le rythme de production et de consommation peut être disparate. Pour gérer cette situation, on décide que les commandes PUT et TAKE sont bloquantes :
  • PUT bloque tant que le champ de transit n'est pas vide.
  • TAKE bloque tant que le champ de transit est vide.
Plutôt que de réaliser des attentes actives consommatrices de ressources processeur, on opte pour l'utilisation d'un verrou ou d'un moniteur ainsi que des mécanismes d'attente passive et de signalisation.

Implanter un tel serveur médiateur contactable concurremment par plusieurs producteurs et consommateurs. Quel est l'inconvénient ici d'utiliser un moniteur avec wait()/notify()/notifyAll() plutôt qu'un verrou et des conditions ?

On peut généraliser le concept d'unique élément de transit par une file d'attente de taille N : les producteurs placent des éléments à la fin d'une file ; les consommateurs les récupèrent en début de file. L'ajout bloque lorsque la file possède N éléments, la récupération bloque tant que la file est vide. L'API du JDK propose des files d'attente bloquantes avec l'interface java.util.concurrent.BlockingQueue (par exemple LinkedBlockingQueue en utilisant une liste chaînée) avec des méthodes bloquantes void put(E e) et E take().

Exercice 3 - Bonus: un proxy TCP

Un proxy a pour mission de jouer le rôle d'intermédiaire entre deux sockets : pour chaque sens de communication, il reçoit les données de l'expéditeur et les transmet à leur destinataire final. Nous allons implanter un proxy utilisant le protocole TCP qui se montre neutre vis-a-vis des données transportées (elles ne sont pas modifiées) mais cela ne l'empêchera pas de conserver quelques statistiques au passage (volume des données échangées). Au lieu de dialoguer directement avec le serveur, le client communiquera avec le proxy qui sera chargé de relayer les données vers/depuis le serveur.