IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Application serveur multi-thread


Sujet :

Java

  1. #1
    Membre éclairé Avatar de richard_sraing
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Avril 2005
    Messages
    483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Avril 2005
    Messages : 483
    Par défaut Application serveur multi-thread
    Bonjour à tous,

    Alors voilà, je me lance dans un projet interne d'application permettant une gestion de plusieurs domaines (courrier, patrimoine, travaux, ...).

    Pour se faire, je souhaite me baser sur une architecture client / serveur. De cette manière, il sera, à mon avis plus simple, de gérer la charge sur le serveur, et ainsi permettre de bien séparer les accès aux données et leurs traitement (côté serveur) de leurs affichage (côte client).

    Situation et analyse :
    J'ai pensé développer l'application de manière à ce qu'elle se lance comme un service de mon service (dans son état final bien sûr).
    Afin de permettre une exécution plus fluide et adaptée du serveur, je veux threader ce dernier.
    Pour ce faire, j'ai penser procéder comme suit :
    - lors du lancement du serveur, je lance 4 threads.
    1. thread à l'écoute des clients : sont seul rôle, est d'accepter les nouvelles connexions de client (ou non si une maintenance ou redémarrage serveur est requis).
    2. thread à l'écoute d'un administrateur (pour la gestion distante du serveur, permettant de voir la charge, des stats d'utilisation, ...)
    3. un thread d'accès à la BD : son seul rôle sera de réaliser les accès à la base de données. Seul ce dernier disposera d'un accès à la BD de manière directe. Tous les autres threads, devront faire transiter leurs demandes par celui-ci (permet de ne pas surcharger les accès à la BD).
    4. un pool de thread : ce dernier aura la charge de réceptionner les demandes des clients (les requêtes en gros), et de les transmettre au thread 3 (accès BD). Une fois qu'ils auront reçu réponse du th3, ils la communiqueront à leur client respectif (au travers de socket).

    J'ai vu, que depuis quelque temps, java a introduit le principe des Callable<T> Future<T> Executors, ...

    Et là, je coince. Je ne suis pas sûr de comprendre comment je peux, de manière "dynamique", passer les informations de mon thread 1. (écoute client) vers mon pool de thread.
    Je pense qu'avec une liste de Callable<Socket>, cela devrait fonctionner, mais sur le reste, je coince.

    Dans le tutoriel, il parle du service de terminaison. Moi, dans mon application, je n'en ai pas besoin, si ? Je souhaite que le thread 1, à l'écoute des demandes de connexions, tourne tout le temps (mise en place d'un système permettant d'interrompre le thread / le mettre en pause / ...).

    Donc, pour l'instant, j'ai ceci comme code :

    La classe principale
    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    package serviceserveur;
    import java.net.Socket;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    /**
     * @version 0.0.1
     * @author raphael threis
     */
    public class ServiceServeur {
     
        static List<Callable<Socket>> lcFileRequetes;
     
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args) {
            ExecutorService esEcouteClient;
            ExecutorService esDbAccess;
            ExecutorService esEcouteAdmin;
            ExecutorService esPoolTraitement;
     
            // Création du thread pour l'écoute sur le port client
            esEcouteClient = Executors.newSingleThreadExecutor();
     
            // Création du thread pour l'écoute sur le port admin
            esEcouteAdmin = Executors.newSingleThreadExecutor();
     
            // Création du thread pour les accès à la base de données
            esDbAccess = Executors.newSingleThreadExecutor();
     
            // Création du Pool de threads pour les actions clientes
            // avec 10 threads pour le traitements
            esPoolTraitement = Executors.newFixedThreadPool(10);
     
            esEcouteClient.submit(new cCaEcouteClient());
            esEcouteAdmin.submit(new cCaEcouteAdmin());
            esDbAccess.submit(new cCaDbAccess());
        }
    }
    La classe cCaEcouteClient
    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    package serviceserveur;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.util.concurrent.Callable;
     
    /**
     * <b>cCaEcouteClient</b> est la classe chargée de la réception des nouvelles connexions de clients.
     * <p>Lors d'une nouvelle connexion, la classe créera une nouvelle socket de communication avec le client et
     * la transmettra à un objet de la classe cCaTraiteClient
     * </p>
     * 
     * @see cCaTraiteClient
     * 
     * @version 0.0.1
     * @author Raphaël THREIS
     */
    public class cCaEcouteClient implements Callable<Integer>{
     
        // <editor-fold desc="Variables de la classe">
        /**
         * Port de connexion pour le client
         */
        private int iPortEcoute;
        /**
         * La socket qui sera mise à l'écoute sur le port iPortEcoute
         * @see cCaEcouteClient#iPortEcoute
         */
        private ServerSocket ssPortEcoute;
        // </editor-fold>
     
        // <editor-fold desc="Accesseurs de la classe">
        /**
         * Initialise la valeur du port d'écoute
         * @param _value la valeur du port d'écoute
         */
        public void setPort(int _value){
            this.iPortEcoute = _value;
        }
        /**
         * Retourne la valeur du port d'écoute.
         * @return La valeur du port d'écoute.
         */
        public int getPort(){
            return this.iPortEcoute;
        }
        // </editor-fold>
     
        @Override
        public Integer call() throws Exception{
            try{
                this.InitializeComponent();
     
                ServiceServeur.lcFileRequetes.add(new cCaTraiteClient(ssPortEcoute.accept()));
     
                return 1;
            }
            catch(IOException ioe){
                throw new IOException(ioe);
            }
        }
     
        /**
         * Initialise la socket d'écoute
         * 
         * @throws IOException 
         */
        private void InitializeComponent() throws IOException{
            try{
                ssPortEcoute = new ServerSocket(iPortEcoute);
            }
            catch(IOException ioe){
                throw new IOException(ioe);
            }
     
        }
    }
    La classe cCaEcouteAdmin
    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    package serviceserveur;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.util.concurrent.Callable;
     
    /**
     * <b>cCaEcouteAdmin</b> est la classe gérant les connexions d'un administrateur.
     * <p>Lors de la connexion d'un administrateur, cette classe sera chargée de répondre à ces demandes.
     * </p>
     * 
     * @version 0.0.1
     * @author Raphaël THREIS
     */
    public class cCaEcouteAdmin implements Callable<Integer>{
     
        // <editor-fold desc="Variables de la classe">
        /**
         * Port sur lequel l'administrateur attaquera le serveur.
         */
        private int iPortAdmin;
        /**
         * La socket qui sera mise à l'écoute sur le port iPortAdmin.
         * 
         * @see cCaEcouteAdmin#iPortAdmin
         */
        private ServerSocket ssEcouteAdmin;
        // </editor-fold>
     
        // <editor-fold desc="Accesseurs de la classe">
        /**
         * Initialisation de la valeur du port d'écoute Admin
         * @param _value la valeur du port d'écoute
         */
        public void setPort(int _value){
            this.iPortAdmin=_value;
        }
        // </editor-fold>
     
        @Override
        public Integer call() throws Exception{
            try{
                this.InitializeComponent();
                return 1;
            }
            catch( IOException ioe){
                throw new Exception(ioe);
            }
        }
     
        /**
         * Initialise la classe avec sa socket d'écoute.
         * 
         * @throws IOException 
         */
        private void InitializeComponent() throws IOException{
            try{
                ssEcouteAdmin=new ServerSocket(iPortAdmin);
            }
            catch(IOException ioe){
                throw new IOException(ioe);
            }
        }
    }
    La classe cCaDbAccess
    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    package serviceserveur;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.util.concurrent.Callable;
     
    /**
     * <b>cCaEcouteAdmin</b> est la classe gérant les connexions d'un administrateur.
     * <p>Lors de la connexion d'un administrateur, cette classe sera chargée de répondre à ces demandes.
     * </p>
     * 
     * @version 0.0.1
     * @author Raphaël THREIS
     */
    public class cCaEcouteAdmin implements Callable<Integer>{
     
        // <editor-fold desc="Variables de la classe">
        /**
         * Port sur lequel l'administrateur attaquera le serveur.
         */
        private int iPortAdmin;
        /**
         * La socket qui sera mise à l'écoute sur le port iPortAdmin.
         * 
         * @see cCaEcouteAdmin#iPortAdmin
         */
        private ServerSocket ssEcouteAdmin;
        // </editor-fold>
     
        // <editor-fold desc="Accesseurs de la classe">
        /**
         * Initialisation de la valeur du port d'écoute Admin
         * @param _value la valeur du port d'écoute
         */
        public void setPort(int _value){
            this.iPortAdmin=_value;
        }
        // </editor-fold>
     
        @Override
        public Integer call() throws Exception{
            try{
                this.InitializeComponent();
                return 1;
            }
            catch( IOException ioe){
                throw new Exception(ioe);
            }
        }
     
        /**
         * Initialise la classe avec sa socket d'écoute.
         * 
         * @throws IOException 
         */
        private void InitializeComponent() throws IOException{
            try{
                ssEcouteAdmin=new ServerSocket(iPortAdmin);
            }
            catch(IOException ioe){
                throw new IOException(ioe);
            }
        }
    }
    Et finalement, la classe cCaTraiteClient
    Code JAVA : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    package serviceserveur;
     
    import java.net.Socket;
    import java.util.concurrent.Callable;
     
    /**
     *
     * @author raphael threis
     */
    public class cCaTraiteClient implements Callable<Socket>{
     
        // <editor-fold desc="Variables de la classe">
        /**
         * La socket de communication avec le client.
         * 
         * @see cCaEcouteClient#call() 
         */
        private Socket sClient;
        // </editor-fold>
     
        // <editor-fold desc="Accesseurs de la classe">
     
        // </editor-fold>
     
        public cCaTraiteClient(Socket _value){
            sClient = _value;
        }
     
        @Override
        public Socket call() throws Exception{
            try{
                this.InitializeComponent();
     
                return null;
            }
            catch(Exception exc){
                throw new Exception (exc);
            }
        }
     
        private void InitializeComponent(){
     
        }
    }

    Donc, ce que je souhaite faire, c'est mettre mon esEcouteClient (thread en attente des connexions clients) en attente
    Une fois une nouvelle demande de connexion arrivée, transmettre l'objet socket créé grâce à la méthode accept à mon pool de thread "esPoolTraitement" par le biais de la "List<Callable<Socket>> lcFileRequetes".

    Ce que je ne sais pas à présent, c'est où je dois placer le code de mon interaction avec le client. Est-ce que je le place dans la classe cCaTraiteClient ou ailleurs.

    Autre question à présent, comment, dans mon cas de figure, dois-je m'y prendre pour que mon pool de threads, se mette en attente sur la List de Callable, et exécute ces derniers une fois qu'il arrive dans la liste ?
    A l'époque où j'étais encore à l'école (4 ans maintenant), nous avions du réaliser un projet client / serveur multi-thread. Si je me souviens bien, nous avions créé un "pipe" de communication entre les divers threads, et nous travaillons avec des "mutex" et nous lancions des évènements lors d'écriture dans les "pipe".

    Quelqu'un pourrait-il me donner une piste sur comment résoudre mon problème, et me permettre d'y voir plus clair.

    En vous remerciant pour l'aide qu'il vous sera possible de me proposer, je reste à votre disposition si vous avez besoin d'une information complémentaire quant à ma manière de travailler.

    p.s.: les Executors et tous ses amis, sont tout nouveau pour moi. Je me souviens, plus ou moins des threads et de ces interface Runnable, mais pour le reste, pas grand chose.

  2. #2
    Membre éclairé Avatar de richard_sraing
    Homme Profil pro
    Responsable de service informatique
    Inscrit en
    Avril 2005
    Messages
    483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : Responsable de service informatique
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Avril 2005
    Messages : 483
    Par défaut
    Bon, je me sens vraiment très

    Je viens de chercher un truc avec mon ami et je suis tombé la dessus.

    J'y vois un peu plus clair maintenant.

    Par contre, toutes remarques est toujours la bienvenue.

Discussions similaires

  1. [C++][serveur multi-threads] prob de connection
    Par Just_the_boss dans le forum C++
    Réponses: 4
    Dernier message: 23/02/2006, 19h09
  2. [Socket] un serveur multi thread
    Par mzt.insat dans le forum Entrée/Sortie
    Réponses: 2
    Dernier message: 12/11/2005, 13h25
  3. Réponses: 7
    Dernier message: 19/10/2004, 19h09
  4. Réponses: 2
    Dernier message: 15/05/2004, 18h33
  5. Réponses: 16
    Dernier message: 30/01/2004, 11h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo