Une application client serveur en Java


Par Worm Imprimer le tutorial Voir son profil

Introduction



Pré-requis : notions de processus, tâches, et protocoles.

Beaucoup d'applications que vous serez amené à développer nécessiteront une bonne compréhension du concept du modèle client - serveur.

En premier lieu, il faut savoir que le client et le serveur représentent chacun une tâche qui est démarrée dans votre processus (ici votre programme java). Deux classes seront donc utilisées : Serveur et Client.

Chacune de ces tâches crée un objet socket qui permettra aux clients et serveurs de communiquer entre eux à travers un protocole (TCP ou UDP) et un port donné. Une toisième classe sera donc utilisée pour ceci : ChaineServCli.

Le serveur



Avant toute chose il nous faut créer un serveur si un client doit venir s'y connecter...C'est pour cela que nous verrons le serveur en premier.

// Toutes les tâches utilisent l'interface Runnable

public class Serveur implements Runnable
{
/** le groupe de tâches */
ExecutorService es;
/** socket du serveur pour attendre les requêtes en provenance des clients */
ServerSocket sockserv = null;
/** objet de communication entre le client et le serveur */
ChaineServCli chaine = null;

/**
* constructeur
* @param es groupe de tâches
*/
public Serveur(ExecutorService es)
{
this.es = es;

try
{
sockserv = new ServerSocket (6020);
}
catch (IOException ex) { }
}

public void run()
{
int nb_clients = 0;
System.out.println("Serveur demarré!");

try
{
while (true)
{
Socket sockcli = sockserv.accept();
nb_clients++;

System.out.println("Connexion établie : "+nb_clients+"ème client");

chaine = new ChaineServCli(es, sockcli);
es.execute(chaine);
}
}
catch (IOException ex) { }
}

public static void main (String args[])
{
ExecutorService es = Executors.newFixedThreadPool(10);
Serveur serv = new Serveur(es);
es.execute(serv);
}
}


Lorsque nous lanceront cette classe, la tâche Serveur sera crée puis executée, appelant ainsi la méthode run() qui attends la connexion d'un client grâce à la méthode accept qui est une méthode bloquante.

A chaque connexion d'un client, un lien est établit entre eux grâce à la classe ChaineServCli qui va effectuer les opérations de notre choix.

Le client




public class Client implements Runnable
{
/** le groupe de tâches */
ExecutorService es;
/** socket pour communiquer avec le client */
Socket sockcli = null;

/**
* constructeur
* @param es groupe de tâches
*/
public Client (ExecutorService es)
{
this.es = es;
}

private int connexion(String url)
{
try
{
sockcli = new Socket (url, 6020);
}
catch (IOException ex)
{ return -1; }

if(sockcli.isConnected())
return 1;
else
return 0;
}

public void run ()
{
boolean boucle = true;

while(boucle)
{
switch(connexion("127.0.0.1"))
{
case 1 :
System.out.println("Connecté");
break;
default :
boucle = false;
break;
}
}
}

public static void main (String args[]) throws Exception
{
ExecutorService es = Executors.newFixedThreadPool(3);
Client client = new Client(es);
es.execute(client);
}
}


Le client se contente d'établir la connexion avec le serveur en créant le socket.

Le lien : ChaineServCli




public class ChaineServCli implements Runnable
{
/** le groupe de tâches */
ExecutorService es;
/** socket pour communiquer avec le client */
Socket sockcli = null;

/**
* constructeur
* @param es groupe de tâches
* @param sockcli socket pour communiquer avec le client
*/
public ChaineServCli (ExecutorService es, Socket sockcli)
{
this.es = es;
this.sockcli = sockcli;
}

public void run()
{
for(int i=0;i<=4;i++)
{
System.out.println("Opération "+i);
}

System.out.println("Fin opérations");
}
}


Le dialogue



Pour l'instant notre application ne fait pas grand chose, elle ne fait qu'éxecuter un certain nombre d'opérations à chaque fois qu'un client se connecte.


La prochaine étape est de faire en sorte que des messages soient échangés entre le client et le serveur, pour cela nous utiliserons dans un premier temps les objets DataOutputStream et DataInputStream.

Nous allons donc utiliser une classe supplémentaire pour lire et écrire dans ces flux :


public class Flux
{
public static String lectureMessage(DataInputStream in) throws IOException
{
int taille = in.readInt();
byte message[]=new byte[taille];
int nb = in.read(message,0,taille);
return new String(message);
}

public static void ecritureMessage(DataOutputStream out, String s) throws IOException
{
byte message[] = s.getBytes();
out.writeInt(message.length);
out.write(message);
}
}


Pour ce qui est de la lecture du message, nous lisons les 4 prochain bits du flux grâce à la méthode readInt() qui retourne ainsi ces bits sous forme d'un entier ce qui équivaut à la taille du message.
Un tableau de bits est ensuite crée auquel nous affectons un tableau de bits de la taille du message.
Le tableau message est remplie grace à la méthode in.read qui récupère les bits de l'offset 0 jusqu'à la fin du message.
Le message est ensuite retourné sous forme de chaine de caractères.

Pour l'écriture du message, nous commencons par récupérer sous forme de bits le message s passé en paramètre que nous affectons au tableau message. On écrit ensuite dans le flux ce message en indiquant la longueur du message, puis le contenu.
« Trouve un travail qui te plaît et plus jamais tu ne travailleras » Confucius


1 commentaire(s)

nedjma-soualah Il y a 2 mois
Salut!! je trouve que votre programme n'est pas complet ( il contient bcp d'erreurs ) il veut pas démarré !! mais merci qnd meme pr ce tuto

Ajouter un commentaire

Vous devez vous être connecté pour poster des commentaires