:: Enseignements :: ESIPE :: E4INFO :: 2013-2014 :: Applications réseaux ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
Client HTTP
|
Exercice 1 - Client Long Sum
Le but de l'exercice est de réaliser un client qui calcule des sommes de long en suivant le protocole TCP suivant:
-
le client envoie un INT (en big endian) donnant le nombre d'opérandes puis chacun des opérandes qui sont des LONG en big endian;
- le serveur répond par un LONG qui correspond à la somme des opérandes.
Remarquez que le serveur ne ferme pas la connection qui peut donc être utilisée pour faire plusieurs sommes.
Vous réaliserez un client
ClientLongSum qui prend en paramètre l'adresse et le port du serveur. Il se lancera par exemple avec:
java upem.net.tcp.ClientLongSum localhost 7777
Votre client va lire des longs au clavier jusqu'à ce que l'utilisateur entre 0. Il enverra ensuite ces longs au serveur en suivant le protocole et affichera
la réponse du serveur.
Si le serveur ferme la connection avant d'avoir envoyé la réponse, votre client
affichera le message:
Connection with server lost.
et quittera.
Vous pouvez tester votre client en lancant le serveur
ServerLongSum.jar comme suit:
java -jar ServerLongSum 7777
Le serveur écoute sur le port 7777.
Pour tester le cas où le serveur ferme la connection de manière
imprévue, vous lancerez le serveur avec l'option
-bug qui
introduit une probabilité que le serveur ferme la connection.
java -jar ServerLongSum -bug 7777
Exercice 2 - Client Concatenation
Le but de l'exercice est de réaliser un client qui se connnecte à un serveur de concatenation de chaînes avec le protocole TCP suivant:
-
le client envoie un INT (en big endian) donnant le nombre de chaînes de caractères, puis chacune de ces chaînes encodée par un INT
(pour la taille en nombre d'octets de la chaîne) suivi des octets représentant la chaîne en UTF-8.
- le serveur répond dans le même format, avec une seule chaîne correspondant à la concatenation de toutes les chaînes, séparées par des virgules.
Vous réaliserez un client
ClientConcatenation qui prend en paramètre l'adresse et le port du serveur. Il se lancera par exemple avec:
java upem.net.tcp.ClientConcatenation localhost 7777
Votre client va lire des chaînes au clavier jusqu'à ce qu'il lise une chaîne vide. Il enverra ensuite ces chaînes (sans la chaîne vide) au serveur en suivant le protocole et affichera la réponse du serveur.
Si le serveur ferme la connection avant d'avoir envoyé la réponse, votre client
affichera le message:
Connection with server lost.
et quittera.
Vous pouvez tester votre client en lancant le serveur
ServerConcatenation.jar comme suit:
java -jar ServerConcatenation 7777
Le serveur écoute sur le port 7777.
Exercice 3 - Client HTTP
Le but de cet exercice est de commencer la réalisation d'un petit client
HTTP. Notre client permettra de faire des requêtes GET et d'en afficher la réponse si c'est du HTML décodée dans le Charset spécifié dans l'entête.
Une requête
GET en HTTP 1.1 est de la forme:
GET / HTTP/1.1
Host: www.w3.org
Chaque ligne est encodée en ASCII et se termine par CRLF (Carriage Return, Line Feed; "\r\n" en java). La requête se termine par une ligne vide. La requête si elle est faite au
serveur
www.w3.org sur le port 80 demande la ressource racine
/ qui est en général la page d'accueil du site.
La réponse du serveur est:
HTTP/1.1 200 OK
Date: Mon, 17 Mar 2014 15:01:27 GMT
Server: Apache/2
Content-Location: Home.html
Vary: negotiate,accept
TCN: choice
Last-Modified: Fri, 14 Mar 2014 16:25:11 GMT
ETag: "8eb4-4f4938388e7c0;89-3f26bd17a2f00"
Accept-Ranges: bytes
Content-Length: 36532
Cache-Control: max-age=600
Expires: Mon, 17 Mar 2014 15:11:27 GMT
P3P: policyref="http://www.w3.org/2001/05/P3P/p3p.xml"
Content-Type: text/html; charset=utf-8
...
Chaque ligne de l'entête est encodée en ASCII et est terminée par CRLF.
L'entête se termine par une ligne vide. La première ligne:
HTTP/1.1 200 OK
donne la version du protocole utilisée pour la réponse
HTTP/1.1,
le code de la réponse
200 et un message décrivant le code de retour
OK.
Les lignes suivantes de l'entête sont de la forme:
clé: valeur
Parmi les informations pertinente,
Content-Length indique que le contenu (c'est à dire le "corps" de la réponse) fait 36532 octets. Cette information est nécessaire car en HTTP/1.1
le serveur ne ferme pas la connection après avoir répondu. Le champ
Content-Type indique que la ressource est du HTML et est encodée en UTF-8.
Il existe un autre mode de transfert appelé
chunked. Ce mode est signalé par le champ suivant:
Transfer-Encoding: chunked
Le principe est décrit
ici. Pour l'instant, il n'est pas nécessaire de regarder ce mode de fonctionnement.
Le traitement de la réponse se fera au moyen d'une classe HTTPReader que vous allez implémenter. Un objet de cette classe contient deux champs : la
SocketChannel sur laquelle la réponse est lue et son buffer de lecture.
Toutes les méthodes de la classe doivent respecter le comportement suivant:
- Le buffer de lecture est en mode écriture avant et après l'appel à la méthode (son contenu n'est pas "prêt" à être lu, mais prêt à être complété s'il reste de la place).
- Aucune lecture sur la socket ne peut être effectuée tant que le buffer de lecture contient des éléments (on doit donc "consommer" tout le contenu du buffer avant de lire à nouveau des données).
- Récupérez les fichiers HTTPReader.java et HTTPException.java qui vous serviront de base.
- Ecrivez la méthode readLineCRLF. Vous pouvez dans un premier temps la tester avec l'exemple du main. Ensuite vous vérifirez que votre fonction passe les tests JUnit du fichier HTTPReaderTest.java (il vous faudra aussi le fichier FakeHTTPServer.java).
- Ecrivez la méthode readHeader. Vous devez renvoyer un objet de la classe HTTPHeader. Pour créer l'objet, vous utiliserez la factory create qui prend en paramètre:
- une String contenant la première ligne de la réponse,
- une map associant à chaque champ sa valeur.
Attention, le header peut contenir plusieurs fois le même champs.
Par exemple,
Set-cookie: x-wl-uid=1smBggFQdYEUGLgg29x3Qr/zAwfq42jdGu0mYszL1+mrt/ABZ8xw43Ise90maJaHGuGvUKVQ+0gM=; path=/; domain=.amazon.fr; expires=Mon, 31-Dec-2035 23:00:01 GMT
Set-cookie: session-id-time=2082754801l; path=/; domain=.amazon.fr; expires=Mon, 31-Dec-2035 23:00:01 GMT
Set-cookie: session-id=276-2784413-9232431; path=/; domain=.amazon.fr; expires=Mon, 31-Dec-2035 23:00:01 GMT
C'est équivalent à ne mettre qu'un seul champ Set-Cokie avec la concatenation des 3 chaînes séparées par des point-virgules.
- Compléter la méthode readBytes.
- Ecrivez un client HTTPClient qui prend en argument l'adresse
d'un serveur et une ressource. Le client demande la ressource au serveur sur
son port 80, il affiche la ressource si c'est du HTML.
Pour l'instant, vous ne traiterez que le cas où la réponse contient un champ
Content-Length.
- Faire en sorte de pouvoir traiter les réponses dans le mode de transfert
chunked. Pour cela implémentez, la methode readChunks dans la classe HTTPReader.
- Modifiez votre client pour prendre en compte les codes de réponse 301
et 302.
© Université de Marne-la-Vallée