Universit´e Paris Sud Licence d’informatique/IUP2 - Ann´ee 2003/2004
TD PAC - Java n10
(Correction)
Applications en mode Client-Serveur
Exercice 1 On d´esire r´ealiser une application de type Serveur de fichiers en mode client-serveur.
1. Le Serveur
Pour cela on va cr´eer une classe Serveur qui poss`edera un attribut de type ServerSocket
qui sera initialis´e dans le constructeur pour attendre des connexions sur un num´ero de port,
´eventuellement pass´e en ligne de commande (sinon on prendra comme port par d´efaut : 3456).
Lors de la connection d’un client, le serveur devra cr´eer un nouveau thread pour traiter les
requ`etes en provenance de ce client. Bien sˆur, pendant ce temps, le serveur devra continuer
d’attendre de nouvelles connection ´eventuelles.
Correction :
/*
* Fichier Serveur.java
*/
import java.io.*;
import java.net.*;
/**
* Serveur de connection pour les clients.
* Le choix du port de communication peut ^etre pass´e en ligne de commande.
*/
public class Serveur {
// Constantes
private static final int PORT_PAR_DEFAUT = 3456;
// Attributs
private ServerSocket _sock;
// Constructeur
public Serveur (int port){
try {
// Creation du socket d’´ecoute
_sock = new ServerSocket (port);
for (;;) {
System.out.println ("Server: en attente ");
// Det´etection d’une connection
Socket s = _sock.accept();
// Cr´eation d’un thread pour erer la connection
(new Connexion(s)).start();
}
} catch (IOException e){
System.out.println("ServerSocket: " + e);
System.exit (1);
}
}
/** programme principal*/
public static void main (String [] args) {
1
int numero_de_port ;
// Choix du numero de port
if (args.length > 0)
numero_de_port = Integer.parseInt(args[0]);
else
numero_de_port = PORT_PAR_DEFAUT;
// Lancement du serveur
Serveur s = new Serveur (numero_de_port);
}
}
2. La gestion des connections
Nous consid`ererons ici tout simplement qu’une requ`ete est simplement une chaˆıne de caract`eres
qui correspond
soit `a un nom d’un fichier a transf´erer (r´esidant sur la machine o`u tourne le serveur)
soit `a la commande fin qui provoque l’arrˆet du serveur.
Le thread traitant les requ`etes sera impl´ement´e par la classe Connexion. Son constructeur est
appel´e avec le Socket issu du accept qu’a fait le serveur. Sa m´ethode run doit lire la requ`ete
en provenance du client, la traiter, fermer la connexion, puis se terminer.
Correction :
/*
* Fichier Connection.java
*/
import java.io.*;
import java.net.*;
/**
* Thread qui g`ere une connection au serveur.
* On peut la faire attendre le temps qu’on veut,
* la planter ´eventuellement, le serveur reste `a
* l’´ecoute des autres demandes de service.
**/
class Connexion extends Thread
{
// Attributs
/** le socket retourn´e par <tt>accept</tt> */
private Socket _sock;
// Constructeur
public Connexion (Socket s)
{
_sock = s;
}
/**
* Traitement d’une requ`ete :<br>
* 1. on lit la requ`ete<br>
* 2. si c’est <tt>‘fin’</tt> on termine le serveur<br>
* 3. sinon on esp`ere que c’est le nom d’un fichier `a transmettre<br>
* on le recopie octet par octet sur le socket.<p>
* A la fin (exception de fin de fichier) on ferme la connexion et on
* termine la thread.
*/
public void run (){
String requete = null;
try {
2
for (;;) {
BufferedReader in = new BufferedReader(
new InputStreamReader(_sock.getInputStream ()));
// lire la requ`ete.
requete = in.readLine();
if (requete.equals ("fin")) {
System.out.println ("Arr^et du serveur par un client");
System.exit (0);
}
// ouvrir le fichier correspondant.
// On utilise un DataInputStream car on ne connait pas la nature du fichier
DataInputStream din = new DataInputStream (new FileInputStream (requete));
System.out.println ("Ouverture du fichier : "+ requete);
// recopier le fichier (on s’en sortira par l’exception de fin de fichier).
DataOutputStream dout = new DataOutputStream (_sock.getOutputStream ());
for (;;)
dout.writeByte (din.readByte ());
}
} catch (FileNotFoundException e) {
System.out.println ("Error: " + e.getMessage ());
} catch (EOFException e) {
System.out.println ("Fichier : "+ requete + " Envoy´e");
} catch (IOException e) {
System.out.println ("run: " + e);
}
try {
_sock.close ();
} catch (IOException e) {}
}
}
3. Le Client
Pour tester notre serveur de fichiers, on va ´ecrire un autre programme qui va demander au serveur
de lui envoyer un fichier. Ce programme prend en argument (dans la ligne de commande)
le nom de la machine correspondant au serveur
le num´ero de port sur lequel se connecter
la requˆete (i.e. le nom du fichier `a transf´erer ou bien ”fin
Il est impl´ement´e avec la classe Client qui utilisera un objet de type Socket pour se connecter
au serveur. Le fichier r´ecup´er´e est enregistr´e localement sous le mˆeme nom que celui utilis´e dans
la requˆete.
Correction :
/*
* Fichier Client.java
*/
import java.io.*;
import java.net.*;
public class Client{
// Constantes
private static final int PORT_PAR_DEFAUT = 3456;
// Attributs
private Socket _sock;
// Constructeur
public Client (String machine, int port, String requete){
DataOutputStream dout=null;
3
try {
// Connection au serveur
_sock = new Socket (machine, port);
// Envoi de la requ`ete au serveur
PrintWriter out = new PrintWriter(_sock.getOutputStream ());
out.println(requete);
out.flush();
if (! requete.equals("fin")) {
// attente de la r´eponse du serveur
DataInputStream din = new DataInputStream(_sock.getInputStream ());
dout = new DataOutputStream(new FileOutputStream(requete));
// on sortira de la boucle par l’exception de fin de fichier
for (;;) {
dout.writeByte(din.readByte ());
}
}
}
/** sortie ’normale’ de la boucle for */
catch (EOFException e) {
try {
dout.close();
_sock.close();
} catch (IOException ex) {
System.err.println(ex);
}
}
/** v´eritable erreur (pas de serveur, etc...) */
catch (IOException e) {
System.err.println (e);
try {
_sock.close ();
} catch (IOException ex) {}
}
}
public static void main (String [] args)
{
int nb_args = args.length;
String machine ;
int numero_de_port = PORT_PAR_DEFAUT;
String requete ;
if ((nb_args < 2) || (nb_args > 3)) {
System.err.println ("Usage: java client <machine> [<port>] <requete>");
}
else {
machine = args[0];
if (nb_args == 2)
requete = args[1] ;
else {
numero_de_port = Integer.parseInt(args[1]);
requete = args[2];
}
Client c = new Client (machine, numero_de_port, requete);
}
}
}
4
1 / 4 100%
La catégorie de ce document est-elle correcte?
Merci pour votre participation!

Faire une suggestion

Avez-vous trouvé des erreurs dans linterface ou les textes ? Ou savez-vous comment améliorer linterface utilisateur de StudyLib ? Nhésitez pas à envoyer vos suggestions. Cest très important pour nous !