Prenez le temps de lire correctement les énoncés, y compris ces remarques pour ne pas répondre à côté de la question...
Le principe de ce TP noté est de vous faire réaliser des
exercices en les corrigeant au fur et à mesure de leur
réalisation. Dès que vous avez réalisé une partie d'un
exercice (typiquement la réponse à une question indiquée par
le symbole ), vous appelez le
correcteur qui viendra vérifier la validité de votre
travail.
Vous pouvez utiliser les entrées-sorties "classiques" (java.io et java.net) ou les "nouvelles" entrées-sorties (java.nio), mais toutes les implémentations se feront en mode bloquant (aucun code non-bloquant ne sera accepté).
Vous écrirez toutes les classes Java nécessaires à ce TP noté
dans un paquetage fr.umlv.ir2.jr.tpnote
. Vous respecterez
les noms de classe spécifiés dans le sujet.
À la fin du temps de composition, lorsque l'examinateur vous le dira, vous enverrez par mail à votre examinateur l'ensemble des classes que vous avez codé, dans l'état où elles se trouvent (même avec des erreurs de compilation). Cela permettra d'ajuster votre évaluation par rapport à ce qui a été vérifié par l'examinateur en séance. N'envoyez aucun mail avant qu'on ne vous le dise, et en tout état de cause vous ne devrez envoyer qu'un seul mail contenant toutes vos classes.
On souhaite dans un premier temps écrire un serveur TCP très simple,
que nous ferons ensuite évoluer. Ce serveur, sous la forme d'une classe TcpIterativeServer,
se démarre en lançant la commande
prompt$ java fr.umlv.ir2.jr.tpnote.TcpIterativeServer <tcpPort>
où tcpPort est le port d'écoute du serveur.
Pour l'instant, ce serveur est itératif, c'est à dire qu'il n'accepte qu'une seule connexion de client à la fois: il ne peut accepter et traiter le client suivant que lorsque la connexion TCP avec le client en cours est fermée.
Dans cette question, le service effectué par ce serveur est le suivant: il affiche à l'écran tous les entiers qu'il reçoit du client connecté, un par ligne; on considère que les entiers sont des int sans se soucier de l'ordre des bytes (le serveur et les clients sont sur la même plateforme: localhost).
Pour tester ce serveur, vous utiliserez le client dont le bytecode est fournit à
l'URL SimpleClient.jar. Ce client se démarre par la commande
prompt$ java -jar SimpleClient.jar <server> <tcpPort>
où <server> est l'adresse du serveur que vous devez développer (donc localhost) et
tcpPort est le port d'écoute du serveur. Ce client envoie tous les entiers qu'il lit au clavier,
un à un, vers le serveur sur la connexion TCP, et il s'arrête quand on tape Ctrl-D (fin de flot) ou Ctrl-C.
Développez la classe TcpIterativeServer. Vous la munirez d'un constructeur qui accepte
le numéro de port en argument, d'une méthode launch() qui démarre le serveur et
d'une méthode main() qui crée un serveur écoutant sur le port passé en argument
sur la ligne de commande et le démarre. Tester qu'il permet d'accepter et de traiter
successivement plusieurs clients SimpleClient.jar sur localhost.
Sans modifier le serveur précédent (vous pouvez en faire une copie ou réutiliser ce qui vous intéresse), on souhaite maintenant écrire un serveur TCP concurrent dans une classe TcpConcurrentServer. Ce serveur rend le même service que le serveur précédent, mais en traitant en concurrence tous les clients qui se sont connectés à lui, dans la limite de maxClients clients simultanés: ce nombre de clients maximum sera passé en argument au lancement du serveur, et au delà de ce nombre, les clients tentant de se connecter devront attendre qu'un client actuel se déconnecte pour pouvoir être servi. En plus de l'entier reçu, le serveur affichera à l'écran l'adresse de la socket (adresse IP et numéro de port) du client de qui il a reçu cet entier.
Le serveur se démarre donc en lançant la commande
prompt$ java fr.umlv.ir2.jr.tpnote.TcpConcurrentServer <tcpPort> <maxClients>
Développez la classe TcpConcurrentServer. Vous la munirez d'un constructeur qui accepte
le numéro de port et le nombre maximum de clients en argument, d'une méthode launch() qui
démarre le serveur et d'une méthode main() qui crée un serveur écoutant sur le port passé en argument
sur la ligne de commande et le démarre. Tester qu'il permet d'accepter et de traiter
simultanément jusqu'à maxClients clients SimpleClient.jar sur localhost.
Sans modifier le serveur précédent (vous pouvez en faire une copie ou réutiliser ce qui vous intéresse), on souhaite maintenant écrire un serveur TCP concurrent dans une classe SumConcurrentServer.
Ce serveur est très semblable au précédent mais au lieu d'afficher les entiers qu'il reçoit de ses clients, il doit en cumuler la somme dans un seul et unique compteur (un même compteur entier pour tous les clients d'un même serveur, qui au démarrage du serveur est initialisé à zéro, et pour lequel on ne se posera pas la question du débordement), et afficher à l'écran la valeur du compteur après chaque ajout d'un entier reçu d'un client.
Le serveur se démarre comme précédement en lançant la commande
prompt$ java fr.umlv.ir2.jr.tpnote.SumConcurrentServer <tcpPort> <maxClients>
Développez la classe SumConcurrentServer et testez-la en utilisant plusieurs
clients SimpleClient.jar sur localhost.
On veut maintenant définir notre propre client, pour modifier le comportement
de SimpleClient.jar. On va donc écrire une classe Client4,
qui se démarrera en lançant la commande
prompt$ java fr.umlv.ir2.jr.tpnote.Client4 <tcpServer> <tcpPort>
et qui devra réaliser les opérations suivantes:
Développez la classe Client4 et testez-la en utilisant plusieurs
instances qui se connectent à votre serveur SumConcurrentServer
démarré sur localhost.
Toujours sans modifier le serveur précédent (vous pouvez en faire une copie ou réutiliser ce qui vous intéresse), on souhaite maintenant écrire une nouvelle version du serveur dans une classe Server5.
Sur la base du service que rendait le précédent serveur SumConcurrentServer, on souhaite que Server5 prenne désormais en compte les éléments suivants:
Développez la classe Server5. Vous ne pourrez la tester qu'après avoir réalisé
la question 6 suivante.
Sans modifier le client précédent (vous pouvez en faire une copie ou réutiliser ce qui vous intéresse), écrivez maintenant une nouvelle version du client dans une classe Client6 qui ajoute à la version précédente les fonctionnalités suivantes:
Développez la classe Client6. Testez-la avec l'application Server5.java.