Le serveur HTTP : Dialogue avec le Client

publicité
Le serveur HTTP : Dialogue avec le Client PeiP2 : Introduction au Web Dino López, Benjamin Miraglio et 1. Introduction Les TPs « Le Serveur HTTP » ont un double objectif : d’une part, vous devez réaffirmer vos connaissances sur le protocole HTTP/1.0, par les méthodes GET et POST vue en cours, éléments nécessaire pour comprendre l’architecture de pages web dynamiques avec, par exemple, PHP, Ajax ou une autre technologie. D’autre part, vous ces TPs doivent vous permettre de réaffirmer également vos connaissances acquises en programmation. Pour cela, pour la suite, nous nous focaliserons uniquement sur le langage de programmation Java. 2. Java et le Réseau Le langage de programmation Java propose de nombreuses primitives pour écrire une application réseau. Java étant un langage de programmation orienté objet de haut niveau, des classes existent déjà pour développer une connexion entre deux machines sans avoir besoin de connaître l'ensemble de primitives qui doivent être appelées pour cela. Cependant, et malheureusement, celles-­‐ci, sont d’assez bas niveau. Pour pallier à ce problème, vous utiliserez la classe Server qui a été définie pour vous, disponible dans la librairie peip.jar (voir les ressources fournies avec ce TP). Celle-­‐ci permet de gérer la connexion au serveur depuis une machine distante, puis d'interagir avec cette machine distante via l'échange de lignes de texte. La création d’une instance de la classe permet de construire un (objet) serveur. La fonction de création (le constructeur) reçoit 2 paramètres facultatifs: •
•
port : qui est le port sur lequel le serveur se met en attente. Par défaut, le port utilisé est le 1234 verbose : qui permet d’avoir un serveur « bavard ». Par défaut, ce paramètre est false. La valeur renvoyée par le constructeur de Server est un objet serveur capable de lire et d'écrire des caractères depuis ou vers son client. Les méthodes d'un serveur créé ainsi sont décrites ci-­‐dessous: •
•
•
acceptConn() se met en attente d’une connexion. Cette méthode bloque l'exécution tant qu'il n’y a pas de client disponible. readline() lit une ligne provenant du client (une ligne signifiant une suite de caractères terminée par un caractère newline). writeline() écrit une ligne vers le client, avec un newline à la fin. Utile pour envoyer un message texte avec saut à la prochaine ligne. •
•
•
write() écrit le contenu d'un buffer vers le client, sans ajouter un newline. A utiliser strictement pour l’envoie d’une longue série de données (ex. un fichier) ou des données binaires. closeConn() termine la connexion avec le client close() ferme le serveur (i.e. accepter une connexion n'est plus possible). Un exemple d’utilisation de cette classe (côté machine distante) est donné ci dessous: 1. import peip.Server; //import de la classe Server du package peip
2. import java.io.*;
3.
4. public class Test {
5.
public static void main(String[] args) {
6.
Server myserver = null;
7.
8.
try {
9.
myserver = new Server(1234, true);
10.
} catch (IOException e) {
11.
System.out.println("Problem while creating server!");
12.
System.exit(-1); // code erreur <> 0 pour signaler qu'il y a un
pbm
13.
}
14.
15.
try {
16.
dialogue(myserver);
17.
} catch (IOException e) {
18.
System.out.println("Problem while talking to the client!");
19.
} finally {
20.
System.out.println("Killing the server");
21.
myserver.close();
22.
}
23.
}
24.
25.
// methode de dialogue correspondant à l'écho par le serveur d'une
(seule) chaine lue cad reçue (envoyée) du client
26.
private static void dialogue (Server myserver) throws IOException {
27.
myserver.acceptConn();
28.
String creply = null;
29.
creply = myserver.readline();
30.
if (creply != null) { //if not EOF, then the client is still there
and we can write to him
31.
myserver.writeline(creply);
32.
creply = null;
33.
}
34.
myserver.closeConn();
35.
}
36. } Listing 1. Serveur simple Dans cet exemple, la ligne 1 importe la classe Server de la librairie peip. La ligne 6 déclare une variable qui peut contenir une instance de la classe Server, et l'initialise à null. Ensuite, le serveur est créé, écoutant sur le port 1234 et désactivant le mode « verbose » (ligne 9). Puis le dialogue avec un client potentiel est possible par le biais de la méthode « dialogue() ». La méthode « dialogue » déclenche une exception en cas d'erreur ce qui demande donc l'utilisation du bloc try...catch. De plus, le « garbage collector » de Java n'étant pas capable de gérer correctement la fermeture de ressources externes, l'utilisation du bloc « finally » pour exécuter une fermeture « manuelle » de notre serveur (et donc de toutes les ressources d'entrée sortie qu'il utilisait) par la méthode close est nécessaire. Le serveur que l'on pilote au sein de la méthode dialogue va accepter les demandes de connexion des clients avec acceptConn (ligne 27). La ligne 29 lit une ligne envoyée par la machine distante (client connecté), qu'on renvoie (en écho!) au client (ligne 31) uniquement si la chaîne reçue est différente de « null » (ligne 30). En effet, la lecture d'un null coté serveur indique la réception d'un « EOF – End of File » qui annonce que la machine cliente a fermé la connexion. Pour travailler avec ce serveur, il suffit de lancer le programme dans un terminal (en indiquant en option l'usage de cette librairie peip.jar, voir dans la partie exercices) et de lancer en tant que client la commande netcat, par exemple. Ci-­‐dessous vous avez un exemple de dialogue entre netcat et notre serveur écrit en Java (ici, la machine où tourne le serveur est aussi la machine où on a lancé netcat, donc on se connecte depuis netcat à « localhost ») : $ netcat localhost 1234
Bonjour, il y a quelqu’un ici ?
Bonjour, il y a quelqu’un ici ?
$
Le serveur que nous avons créé marche bien, mais il a 2 fortes inconvénients : 1. ce serveur ne peut servir qu’un seul client (i.e. une fois qu’un client a été servi et s'est déconnecté, le serveur meurt). Ce problème peut être résolu à l’aide d’une boucle infinie côté serveur: 2. une seule ligne peut-­‐être lue par le serveur. Puis le serveur fait un écho de ce qu’il a lu et ferme la connexion avec le client. Le premier problème peut-­‐être facilement résolu avec l’introduction d’une boucle while autour de l’appel à dialogue(). while (true) {
dialogue(myserver);
} En effet, l'utilisation d'un bloc while permet le traitement de plusieurs clients successifs, et c'est de cette manière là que nous allons procéder pour les exercices suivants. 3. Quelques détails techniques La librairie peip utilisée dans l’exemple vous est fournie sous la forme d'un fichier jar (peip.jar). Assurez-­‐vous d'indiquer le chemin vers ce fichier jar. Par exemple, si vous travaillez par ligne de commande, vous utiliserez le paramètre -­‐classpath de javac pour la compilation et le paramètre -­‐cp de java pour l'exécution. Si votre installation Java (compilateur) vous dit que la version utilisée pour fabriquer le .jar n'est pas compatible avec votre version de Java, pas de panique. Récupérez le fichier Server.java (en bas de cette page) et soit, ré-­‐fabriquez un peip.jar (en décommenttant la ligne 1); ou sinon, compilez ce .java en même temps que votre propre programme, après l'avoir placé dans le même répertoire. Si vous utilisez un IDE, référez-­‐vous à sa documentation afin d'ajouter la librairie peip.jar à votre projet Java. Par exemple, dans le cas d'Eclipse vous pouvez visiter http://wiki.eclipse.org/FAQ_How_do_I_add_an_extra_library_to_my_project%27s_classpat
h%3F 4. Exercices 1. Mettez en place le serveur avec une boucle infinie et testez-­‐le avec la commande netcat (jouant le rôle de client). Vérifiez bien que vos clients successifs peuvent se connecter au serveur sans avoir à devoir le relancer à chaque fois. 2. Modifiez votre serveur pour qu'il lise les lignes envoyées par le client jusqu'à l'obtention d'une ligne vide. À la réception de la ligne vide, envoyez le message « Bien reçu. Au revoir. » et fermez la connexion avec le client. Validez votre programme avec la commande netcat en tant que cliente. Relancez (et vérifiez que cela fonctionne) un nouveau client sans avoir besoin de lancer à nouveau le serveur. 
Téléchargement