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 connexion 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.
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.
La méthode main
appelle getFixedSizeResponse
avec :
var google = new InetSocketAddress("www.google.fr", 80); getFixedSizeResponse("GET / HTTP/1.1\r\nHost: www.google.fr\r\n\r\n", google, 512);Notre client envoie donc la requête GET ... au serveur HTTP
www.google.fr
sur le port 80. Une fois que la connexion est fermée en écriture, le serveur renvoie la page d'accueil de Google.HTTP/1.1 200 OK Date: Tue, 27 Feb 2018 21:35:47 GMT Expires: -1 Cache-Control: private, max-age=0 Content-Type: text/html; charset=ISO-8859-1 P3P: CP="This is not a P3P policy! See g.co/p3phelp for more info." Server: gws X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN Set-Cookie: 1P_JAR=2018-02-27-21; expires=Thu, 29-Mar-2018 21:35:47 GMT; path=/; domain=.google.fr Set-Cookie: NID=124=VPRK8vfhv8XgJdFfzadSN-WSa5C7RvGCOlWBqZ_-Hvnv9O1wWnKSMcXUY3HyNxC2wCoafO7VJ482Bp0njEQV7PtMJeoPjtr_fWH2-
Écrivez ensuite la fonction getUnboundedResponse
qui doit lire la réponse
quelle que soit la taille de la chaîne de caractères renvoyée par le serveur.
Lors des lectures sur la SocketChannel
, votre méthode doit gérer à la fois le cas où la connexion est fermée et celui où le buffer est plein, ce qui peut mener à un code peu lisible. Une solution pour clarifier le code est d'avoir une méthode annexe qui s'occupe de remplir un buffer, si possible.
Écrivez une méthode boolean readFully(ByteBuffer buffer, SocketChannel sc)
qui remplit complètement le buffer
(si c'est possible) en lisant sur la SocketChannel sc
. De plus, la méthode renvoie false
si read
a renvoyé -1 et true
sinon.
"Simplifiez" votre code en utilisant la méthode readFully
.
Le client précédent a deux inconvénients majeurs : il n'est pas très efficace car il 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 envoie et reçoit des informations dont le format est précisé par un protocole.
long
en suivant le protocole TCP suivant :
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;
long
correspondant à la somme des opérandes.
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 7777La 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.
Connection with server lost.et quittera.
Remarque : vous pouvez utiliser la méthode readFully
écrite lors de l'exercice précédent...
Vous pouvez tester votre client en lançant le serveur ServerLongSumTCP.jar comme suit :
java -jar ServerLongSumTCP.jar 7777
-bug
qui
introduit une probabilité que le serveur ferme la connexion.
java -jar ServerLongSumTCP.jar -bug 7777
Le même genre de protocole peut être mis en place pour échanger des chaînes de caractères.
int
(en Big Endian) donnant le nombre de chaînes de caractères,
puis envoie chacune de ces chaînes encodées 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.
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.
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 7777Votre client va lire des chaînes au clavier jusqu'à ce qu'il lise une chaîne vide. Il enverra ensuite ces chaînes (une par une et sans la chaîne vide) au serveur en respectant le protocole et affichera la réponse du serveur.
Connection with server lost.et quittera.
Vous pouvez tester votre client en lançant le serveur ServerConcatenationTCP.jar comme suit :
java -jar ServerConcatenationTCP.jar 7777Le serveur écoute sur le port 7777.
Remarque : envoyer les chaînes une par une revient à faire beaucoup d'appels à write()
ce qui n'est pas très efficace. On peut également préparer tous les buffers encodés, mais on stocke ainsi beaucoup de données. La "bonne" façon de faire serait d’utiliser un buffer de taille fixe, et de le remplir "au mieux" avant chaque appel à write()
.