Cyril Rabat


Serveur en mode connecté multi-threadé

 11/12/2013     18/10/2017      Programmation Java      Programmation client/serveur      Sockets   

Créer un thread associé à chaque connexion vers un client

   Cet article présente comment développer simplement un serveur en mode connecté multi-threadé en Java.

Mots-clefs :   Java     socket     mode connecté     TCP     multi-thread   

L'archive suivante contient l'ensemble des fichiers de cet article :

 TCP multithread.zip

Le programme serveur

Cette classe correspond au serveur. Une fois exécuté, le serveur se met en attente de la connexion d'un client. Lorsqu'une connexion est établie, le serveur démarre un thread dont la classe associée est ThreadConnexion. L'exécution du serveur est infinie et doit être interrompue manuellement.

import java.io.IOException;
 
import java.net.ServerSocket;
import java.net.Socket;
 
/**
 * Classe correspondant à un serveur TCP multithreadé.
 * Le client envoie la chaine 'Bonjour' et lit une réponse de la part du serveur.
 * Le client envoie ensuite la chaine 'Au revoir' et lit une réponse.
 * Le numéro de port du serveur est spécifié dans la classe ServeurTCP.
 * @author Cyril Rabat
 * @version 18/10/2017
 */
public class ServeurTCPMulti {
 
    public static final int portEcoute = 5001;
 
    public static void main(String[] args) {
        // Création de la socket serveur
        ServerSocket socketServeur = null;
        try {    
            socketServeur = new ServerSocket(portEcoute);
        } catch(IOException e) {
            System.err.println("Création de la socket impossible : " + e);
            System.exit(-1);
        }
 
        // Attente des connexions des clients
        try {
            Socket socketClient;
            while(true) {
            socketClient = socketServeur.accept();
            ThreadConnexion t = new ThreadConnexion(socketClient);
            t.start();
            }
        } catch(IOException e) {
            System.err.println("Erreur lors de l'attente d'une connexion : " + e);
            System.exit(-1);
        }
 
        // Fermeture de la socket
        try {
            socketServeur.close();
        } catch(IOException e) {
            System.err.println("Erreur lors de la fermeture de la socket : " + e);
            System.exit(-1);
        }
    }
 
}

 Télécharger le fichier

La classe associée aux threads

Cette classe correspond au thread de traitement pour chaque connexion d'un client. Dans le constructeur, les flux d'entrée et de sortie de la socket sont récupérés. Le code principal se trouve dans la méthode run.

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.PrintWriter;
 
import java.net.Socket;
 
/**
 * Classe correspondant au thread associe à chaque connexion d'un client.
 * @author Cyril Rabat
 * @version 18/10/2017
 */
public class ThreadConnexion extends Thread {
 
    private BufferedReader input;
    private PrintWriter output;
    private Socket socketClient;
 
    public ThreadConnexion(Socket socketClient) {
        this.socketClient = socketClient;
 
        // Association d'un flux d'entrée et de sortie
        try {
            input = new BufferedReader(new InputStreamReader(socketClient.getInputStream()));
            output = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socketClient.getOutputStream())), true);
        } catch(IOException e) {
            System.err.println("Association des flux impossible : " + e);
            System.exit(-1);
        }
    }
 
    @Override
    public void run() {
        // Lecture de 'Bonjour'
        String message = "";
        try {
            message = input.readLine();
        } catch(IOException e) {
            System.err.println("Erreur lors de la lecture : " + e);
            System.exit(-1);
        }
        System.out.println("Lu: " + message);
 
        // Envoi de 'Bonjour'
        message = "Bonjour";
        System.out.println("Envoi: " + message);
        output.println(message);
 
        // Lecture de 'Au revoir'
        message = "";
        try {
            message = input.readLine();
        } catch(IOException e) {
            System.err.println("Erreur lors de la lecture : " + e);
            System.exit(-1);
        }
        System.out.println("Lu: " + message);
 
        // Envoi de 'Au revoir'
        message = "Au revoir";
        System.out.println("Envoi: " + message);
        output.println(message);
 
        // Fermeture des flux et des sockets
        try {
            input.close();
            output.close();
            socketClient.close();
        } catch(IOException e) {
            System.err.println("Erreur lors de la fermeture des flux et des sockets : " + e);
            System.exit(-1);
        }
    }
 
}

 Télécharger le fichier

Le programme client

Cette classe correspond au client. Il envoie une chaîne de caractères au serveur et termine son exécution immédiatement.

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.PrintWriter;
 
import java.net.Socket;
import java.net.UnknownHostException;
 
/**
 * Classe correspondant à un client TCP.
 * Le client envoie la chaine 'Bonjour' et lit une réponse de la part du serveur.
 * Le client envoie ensuite la chaine 'Au revoir' et lit une réponse.
 * Le numéro de port du serveur est spécifié dans la classe ServeurTCPMulti.
 * @author Cyril Rabat
 * @version 18/10/2017
 */
public class ClientTCPMulti {
 
    public static final int portEcoute = 5001;
 
    public static void main(String[] args) {
        // Création de la socket
        Socket socket = null;
        try {
            socket = new Socket("localhost", portEcoute);
        } catch(UnknownHostException e) {
            System.err.println("Erreur sur l'hôte : " + e);
            System.exit(-1);
        } catch(IOException e) {
            System.err.println("Création de la socket impossible : " + e);
            System.exit(-1);
        }
 
        // Association d'un flux d'entrée et de sortie
        BufferedReader input = null;
        PrintWriter output = null;
        try {
            input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            output = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
        } catch(IOException e) {
            System.err.println("Association des flux impossible : " + e);
            System.exit(-1);
        }
 
        // Envoi de 'Bonjour'
        String message = "Bonjour";
        System.out.println("Envoi: " + message);
        output.println(message);
 
        // Lecture de 'Bonjour'
        try {
            message = input.readLine();
        } catch(IOException e) {
            System.err.println("Erreur lors de la lecture : " + e);
            System.exit(-1);
        }
        System.out.println("Lu: " + message);
 
        // Envoi de 'Au revoir'
        message = "Au revoir";
        System.out.println("Envoi: " + message);
        output.println(message);
 
        // Lecture de 'Au revoir'
        try {
            message = input.readLine();
        } catch(IOException e) {
            System.err.println("Erreur lors de la lecture : " + e);
            System.exit(-1);
        }
        System.out.println("Lu: " + message);
 
        // Fermeture des flux et de la socket
        try {
            input.close();
            output.close();
            socket.close();
        } catch(IOException e) {
            System.err.println("Erreur lors de la fermeture des flux et de la socket : " + e);
            System.exit(-1);
        }
    }
 
}

 Télécharger le fichier

Exécution

Pour tester le client et le serveur, vous devez dans un premier temps compiler les classes puis exécuter le serveur. Une fois le serveur démarré, le client peut ensuite être exécuté. À noter que le serveur n'interrompt pas son exécution une fois les échanges terminés et il est possible d'exécuter plusieurs clients.

Articles connexes


Version de cette page Mercredi 16 Décembre 2015

© Cyril Rabat 2018

Connexion

Mot de passe perdu

Dernières nouvelles

20/07/2020 Vous pouvez consulter la page "prérentrée" pour avoir les informations sur les journées de prérentrées en Licence INFO.
16/07/2020 La première phase des inscriptions se termine le 21 juillet. La période pour la deuxième phase est du 19 au 31 août.
25/06/2020 La période pour la phase complémentaire pour la procédure VES est fixée du 10 juillet 2020 au 24 août 2021.
29/05/2020 Le jury de fin d'année aura lieu le jeudi 11 juin, les examens de deuxième session du 22 juin au 3 juillet et le jury de deuxième session le jeudi 16 juillet.

Contact

Courriel :
cyril.rabat [at] univ-reims.fr

Téléphone :
+33-326-91-33-81

Facebook :
lien Facebook direct