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

Collection et Stream Java Discussion :

Collection et multi Thread


Sujet :

Collection et Stream Java

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut Collection et multi Thread
    Bonjour, je suis en train de faire un serveur / client pour communiquer sur un réseau. Mais j'ai plusieurs problèmes et j'aimerai avoir votre avis. En gros j'ai :
    La classe Serveur :
    Code : 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
     
    public class Serveur
    {
         ArrayList<client> clients ;   
     
         public synchronized void sendAll(){}
     
         public synchronized void sendTo(){}
     
         public synchronized void AddClient(){}
     
         public synchronized void delClient(){}
     
         public synchronized final List<Client> getClient(){}
     
    }
    Ensuite j'ai ma classe client : ( Gestion des clients ).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    public class Client {
         objetProtocole protocole ;
         String pseudo ;
     
         public String getPseudo(){}
         public void setPseudo(String pseudo){}
    }
    Classe protoles ( Faut-il en faire une pour chaque client ? utiliser un Singleton... pour le moment j'utilise un Singleton , ou ne serait-il pas mieux d'utiliser une classe interne dans serveur... )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public class Protocole {
        public synchronized public void parseClientMessage(){}
         public synchronized public void parserServeurMessage(){}
    }
    // Cette classe me permet de parser les messages et de mettre en forme les autres messages.


    En gros que le serveur puisse :
    - Parser les messages des clients
    - Envoye un message à un client ou plusieur
    - Pouvoir retourner la liste des clients à un autre clients
    - J'aimerais que le serveur puissse faire un kick automatique donc dois-je mettre cette méthode dans protocole ou la classe serveur...

    Mais je suis perdu un peu pour le moment. donc si vous pouviez me donner un coup de main...

    Merci de votre aide

  2. #2
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    salut

    Pour la gestion des clients, une bonne solution que j'ai adopté pour mon jeu multijoueurs c'est de les gérer selon des groupes. Ca permet d'envoyer les bonnes choses aux bonnes personnes et de facilement lister les clients :
    Code : 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
    public class GroupStore implements Serializable
    {
    	static final long serialVersionUID = 3L;
     
    	private HashMap<String,LinkedList> groupStore;
     
    	public GroupStore()
    	{
    		groupStore = new HashMap<String,LinkedList>();
    	}
     
    	private void addGroup(String ref) //ref: nom du groupe
    	{
    		groupStore.put(ref,new LinkedList());
    	}
     
    	public void removeGroup(String ref)
    	{
    		groupStore.remove(ref);
    	}
     
    	public LinkedList getGroup(String ref)
    	{
    		return groupStore.get(ref);
    	}
     
    	public void addToGroup(Object o, String ref)
    	{
    		System.out.println("groupStore:"+groupStore);
    		LinkedList ll = groupStore.get(ref);
    		if(ll==null) addGroup(ref);
    		groupStore.get(ref).add(o);
    	}
     
    	public void removeFromGroup(Object o, String ref)
    	{
    		LinkedList ll = groupStore.get(ref);
    		if(ll!=null)ll.remove(o);
    	}
    }
    - J'aimerais que le serveur puissse faire un kick automatique donc dois-je mettre cette méthode dans protocole ou la classe serveur...
    ça semble plus logique d'avoir ça dans une classe "Commande".
    là c'est à toi de voir.

    Sinon quand tu mets le mot clé synchronized partout, je trouve ça bizarre. Moi j'en aurai pas mis dans les methode où il n'y a que lecture des données (une méthode synchronisée je crois que c'est la plus longue d'accés aprés une methode invoquée par reflexion !).
    Je trouve que le mieux c'est d'envoyer/recevoir les données selon une queue de messages(je suppose que tu utilises pas nio) (essaye de voir dans ça: ).
    Comme ça, tes differents thread clients alimentent la queue et le thread où tu gere tous les messages n'a plus qu'à lire un par un les messages.

    Voilà, j'ai essayé de t'aider avec le peu que je sais

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut
    En gros mon code ressemble a ceci :

    Un client :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    // Ecoute les message des clients :
    public void run()
    {
       String buffer ;
       while(  ( carLu = in.read() )  != -1 )
       {
          buffer+= carLu ;
          if( carLu = \n et carLuAvant = \r )
          {
             monObjetProtocol.parseClientMessage( buffer ) ;
             /* monObjetProtocol est identique pour chaque client */
          }
       }
    }
    La méthode parseClientMessage marche en gros comme ca :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public synchronized void parseClientMessage(String message )
    {
       if( regexMessageperso == true )
       {
           sendTo( message, clientDestinataire );
       }
       else
       {
           sendAll( message ) ;
        }
    }
    D'ou l'utilisation de synchronized.


    Donc le mieux serait d'avoir une queue alimenté par les clients + lesMessageServeur
    Et de l'autre la classe Protocole qui li et vide la queue ?

  4. #4
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    Si les données envoyées dépassent la vingtaine de bytes (je dis ça un peu au pif), vaudrait mieux utiliser readFully au lieu de lire caractère par caractère non (y'a un gain de vitesse) ? Si oui, il suffit de réservéer des bytes en tête de message pour la taille du message envoyé, comme ça à la reception il suffit de lire ces bytes pour connaitre la taille et de lire la suite avec un readfully.
    Pour ce qui est d'utiliser une queue, moi perso je trouve ça trés pratique, au moins la seule chose à synchroniser c'est cette queue et donc si tu utilises SynchronousQueue le travail est déjà fait.
    Dans mon cas j'utilise énormément les listes de l'api Javolution qui offre une vue synchronisée (FastList, etc...) et qui en plus sont recyclable (donc trés peu de créations d'objets).

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut
    Peut tu me montrer un exemple parce que je ne voie pas du tout comment je peux faire avec ta méthode...
    En effet je regarde et je test mais je suis obligé de synchronized mes méthodes...

  6. #6
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    En fait faudrait que tu definisses une classe abstraite Message.
    Dans cette classe, tu déclares au moins une structure commune pour contenir n'importe quel type de message, par exemple un simple tableau de bytes mais aussi des méthodes communes comme send(Group group) ou getMessageByteArray()

    Ensuite, pour ta queue qui s'occupe d'empiler les messages à envoyer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ConcurrentLinkedQueue<Message> messageOutQueue = new  ConcurrentLinkedQueue<E><Message>();
    *

    et celle qui empile les messages reçus:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ConcurrentLinkedQueue<Message> messageInQueue = new  ConcurrentLinkedQueue<E><Message>();
    *

    Tu peux par exemple stocker ces 2 queues en statique dans une class MessageInOut.

    *ConcurrentLinkedQueue<E> permet de faire des opérations de lecture/écriture/suppression sans à y mettre d'accesseurs synchronisés ! Donc ça convient bien à ton cas je pense.

    Depuis le Thread client, à la reception, il faudra que tu recupères le message et le mette dans un tableau de bytes. Ensuite tu peux créer un objet qui dérive du type Message avec ce tableau et tu empiles cet objet dans messageOutQueue en faisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MessageInOut.messageOutQueue.add(monObjetMessage);
    Le Thread qui s'occupe de lire les éléments empilés de messageOutQueue va récupéré l'élément le plus vieux de la queue en faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Message messageLu = MessageInOut.messageOutQueue.poll()
    et va appeler sa méthode send héritée de Message.

    Ce même Thread s'occupe aussi de lire les éléments empilés de messageInQueue.

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut
    Donc si je comprend bien.

    la classe serveur
    Code : 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
     
     
     List<Client> clients = new ArrayList<Client>();
     
     public void add(Client client)
     {
         clients.add(client);
     }
     
     public void remove(Client client)
     {
         clients.remove(client);
     }
     
     public List clientsList()
      {
          return new CopyOnWriteArrayList<Client>(clients);
      }
     
      public void run()
      { 
         while(true)
         {
           Socket socket = serversocket.accept();
           Client client = new Client(socket);
           add(client);
         }
      }
    la classe client :
    Code : 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
     
     
    public synchronized OutClient getOut()
    {
       return outClient ; // permet de récupérer le flux de sortie du client
    }
     
    public void run()
    {
      while(true)
      {
         String message = in.lireMessage();
         MessageInOut.messageInQueue.add(message);
      }
      serveur.remove( this );
    }
    la classThreadProtocol
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    public void run()
    {
      while(true)
      {
        String message = MessageInOut.messageInQueue.poll();
        // parser le message et construire un nouvel objet de type Message
        MessageInOut.messageOutQueue.add(ajoutNouveauMessage);
      }
     
    }
    la classe MessageInOut:
    Code : 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
     
    public class MessageInOut
    {
      public static ConcurrentLinkedQueue<String> In = new ConcurrentLinkedQueue<String>();
     
      public static ConcurrentLinkedQueue<String> Out = new ConcurrentLinkedQueue<Message>();
     
       public send(Message Message)
       {
          if( Message.type == true ) // privée
          {
             Message.client.getOut( Message.client.contenu );
          }
          else
          {
              for( Client cl = serveur.clientsList() )
              {
                 cl.getOut( Message.client.contenu );
              }  
          }
       }
     
       //Le thread qui li Out
       public void run()
       { 
          while(true)
          {
               send(  Out.poll() ) ;
          }
       }
     
    }

    la classe message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public class message
    {
       public String contenu ;
     
       public boolean type ; // privée ou pour tout le réseaux ;
     
       public Client client; // si privée, client destinataire ;
    }

    En gros, je doit faire ceci ?

  8. #8
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    C'est pas exactement comme je pensais mais ça ressemble. Demain j'essaierai de coder ça et de le publier ici .
    Par contre à quoi va servir cette application client/serveur ?

    Détails: tu as une classe client et une classe serveur. Ca veut dire qu'un client agit aussi comme serveur ? Autre chose,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if( Message.type == true )
    ne doit pas passer à la compilation , si ?

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut
    En faite, je veux faire une petite application client / serveur pour communiquer sur un réseaux. Ici, nous programmons le serveur. ( un client peut envoyer un message à un autre client, tout les clients du réseaux.... )

    La classe serveur permet de configurer / démarrer le serveur et la classe contient la liste des clients.

    La classe client permet de stocker ( les informations relative au client ) et démarrer un thread quand un client ce connecte.

  10. #10
    Membre chevronné Avatar de Rayndell
    Étudiant
    Inscrit en
    Mai 2007
    Messages
    289
    Détails du profil
    Informations personnelles :
    Âge : 38

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2007
    Messages : 289
    Par défaut
    Citation Envoyé par orelero
    C'est pas exactement comme je pensais mais ça ressemble. Demain j'essaierai de coder ça et de le publier ici .
    Par contre à quoi va servir cette application client/serveur ?

    Détails: tu as une classe client et une classe serveur. Ca veut dire qu'un client agit aussi comme serveur ? Autre chose,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if( Message.type == true )
    ne doit pas passer à la compilation , si ?
    Cela passe tout à fait à la compilation si type est un booléen, c'est juste que le == true est tout à fait inutile.

  11. #11
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    Salut, aprés 2 heures de programmation, j'ai fait ça :
    (J'ai eu la flemme de faire un client qui peut s'y connecter. Si tu veux je le ferai)

    Code : 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
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    import java.util.concurrent.*;
    import java.net.*;
    import java.util.*;
    import java.io.*;
     
     
    //************************SERVEUR****************************
    public class ClientServeur
    {
    	public static void main(String[] args)
    	{
    		Server server = new Server(8081); //port 8081 ou autre
    		server.start();
    	}
    }
     
     
    class Client extends Thread
    {
    	public InputStream _inputStream;
    	public OutputStream _outputStream;
     
    	private Socket _socket;
    	private String _groupName;
    	private String _name;
     
    	Client(Socket socket)
    	{
    		_groupName = null;
    		_socket = socket;
    		try
    		{
    			_inputStream = _socket.getInputStream();
    			_outputStream = _socket.getOutputStream();
    		}
    		catch(Exception e) {e.printStackTrace();}
    	}
     
    	public void run()
    	{
    		//IMPLEMENTE COMME TU VEUX POUR LIRE LES MESSAGES ENTRANTS
    	}
     
    	public void setGroupName(String groupName)
    	{
    		_groupName = groupName;
    	}
    }
     
     
    class MessageInOut extends Thread
    {
    	//Listes servant à empiler les messages entrants/sortants
    	//(Accés "Thread-safe", donc pas besoin de créer d'accesseurs synchronisés)
    	private ConcurrentLinkedQueue<MessageOut> _messageOutQueue;
    	private ConcurrentLinkedQueue<MessageIn> _messageInQueue;
    	private Server _serverReference;
     
    	MessageInOut(Server server)
    	{
    		_serverReference = server;
    	}
     
    	public void init()
    	{
    		_messageOutQueue = new  ConcurrentLinkedQueue<MessageOut>();
    		_messageInQueue = new  ConcurrentLinkedQueue<MessageIn>();
    	}
     
    	public void run()
    	{
    		while(_serverReference._isRunning)
    		{	
    			long date1 = System.nanoTime()/1000000;
    			//lit et enlève de la pile les messages arrivants
    			MessageIn messageIn = _messageInQueue.poll();
     
    			//lit et enlève de la pile les messages partants
    			MessageOut messageOut = _messageOutQueue.poll();
     
    			//Régule la vitesse de traitement à environ 16hz. Tu peux l'améliorer en la baissant
    			long delta = System.nanoTime()/1000000-date1; 
    			try{ sleep((delta > 60) ? 0 : 60-delta); } catch(Exception e){e.printStackTrace();}
    		}
    		System.out.println("fin de lecture des messages entrants/sortants");
    	}
     
    	//traite les messages entrants
    	public void treatMessageIn(MessageIn message)
    	{
    		byte command = message.getMessageByteArray()[0];
    		switch(command)
    		{
    			case 0 :
    				//PAR EXEMPLE cette commande 0 correspond à un message venant d'un client
    				// et il faut le retransmettre tel quel à tous les clients
    			break;
    			case 1 :
     
    			break;
    			case 2 :
     
    			break;
     
    			default : System.out.println("commande entrante inconnue");
    		}
    	}
     
    	//traite les messages sortants
    	public void treatMessageOut(MessageOut message)
    	{
    		byte command = message.getMessageByteArray()[0];
    		switch(command)
    		{
    			case 0 :
     
    			break;
    			case 1 :
     
    			break;
    			case 2 :
     
    			break;
     
    			default : System.out.println("commande sortante inconnue");
    		}
    	}
    }
     
     
    abstract class Message
    {
    	//Stockage de tous les messages sous tableau de bytes
    	private byte[] _MessageByteArray;
     
    	Message(byte[] data)
    	{
    		_MessageByteArray = data;
    	}
     
    	public byte[] getMessageByteArray()
    	{
    		return _MessageByteArray;
    	}
    }
    class MessageIn extends Message
    {
    	MessageIn(byte[] data)
    	{
    		super(data);
    	}
    }
    class MessageOut extends Message
    {
    	private String _groupName;
     
    	MessageOut(byte[] data,String groupName)
    	{
    		super(data);
    		_groupName =groupName;
    	}
     
    	public void send(Server server)
    	{
    		ArrayList<Client> clientListGroup = server._groupStore.getClientListGroup(_groupName);
    		Iterator<Client> iterator = clientListGroup.iterator();
    		//envoie le message aux participants du groupe
    		while(iterator.hasNext())
    		{
    			Client client = iterator.next();
    			//ICI ECRIT COMMENT TU VEUX ENVOYER LE MESSAGES SUR client._outPutStream
     
    		} 
    	}
    }
     
     
    class Server extends Thread
    {
    	private ServerSocket _serverSocket;
    	public Boolean _isRunning;
    	private int _port;
    	public GroupStore _groupStore;
    	private MessageInOut _messageManager;
     
    	Server(int port)
    	{
    		_isRunning = new Boolean(false);	
    		_port = port;
    		_groupStore = new GroupStore();
    		_messageManager = new MessageInOut(this);
    		_messageManager.init();
    	}
     
    	public void run()
    	{
    		try
    		{
    			_serverSocket = new ServerSocket(_port); 
    			_isRunning = new Boolean(true);	
    			_messageManager.start();
    			while(_isRunning)
    			{
    				//bloquant sur accept()
    				Socket clientSocket = _serverSocket.accept();
    				Client client = new Client(clientSocket);
    				//ajoute le client à un groupe principale nommé "MainGroup"
    				_groupStore.addToGroup(client,"MainGroup");
    			}	
    		}
    		catch(Exception e){e.printStackTrace();}
    		System.out.println("le serveur a été stoppé");
    	}
     
    	public void Quit()
    	{
    		//stope le serveur
     
    		try
    		{
    			_serverSocket.close();
    		}
    		catch(Exception e){e.printStackTrace();}
    	}
    }
     
     
    class GroupStore
    {
    	//Classe permettant d'affecter un Client à un groupe
    	//trés utile pour savoir à qui envoyer un message (ex: groupe des bannis, kickés ;),
    	//, les admins, les groupes privés...
    	//Attention : un Client peut appartenir à plusieurs groupes
    	// (donc on ne doit jamais avoir besoin d'envoyer à plusieurs groupe)
    	private HashMap<String,ArrayList<Client>> _storageMap;
     
    	public void addToGroup(Client client,String groupName)
    	{
    		//créer le groupe s'il n'existe pas
    		if(!_storageMap.containsKey(groupName)) _storageMap.put(groupName,new ArrayList<Client>());
    		ArrayList<Client> clientGroupList = _storageMap.get(groupName);
    		client.setGroupName(groupName);
    		clientGroupList.add(client);
    	}
     
    	public void removeFromGroup(Client client,String groupName)
    	{
    		if(!_storageMap.containsKey(groupName)) return;
    		ArrayList<Client> clientGroupList = _storageMap.get(groupName);
    		client.setGroupName("");
    		clientGroupList.remove(client);
    	}
     
    	public ArrayList<Client> getClientListGroup(String groupName)
    	{
    		return _storageMap.get(groupName);
    	}
    }
     
    //************************CLIENT****************************
    J'ai essayé de commenter suffisement, j'espère que ça t'aidera

    Ca serait cool d'avoir l'avis d'autres personnes svp

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut
    Dans la classe client, la méthode run(). A chaque fois que l'on reçois un message on va faire :

    MessageInOut.treatMessageIn( messageIn ) ?

    ou plutot :

    MessageInOut._messageInQueue( messageIn ) ?

    parce que je ne comprend pas quand treatMessageIn, treatMessageOut, et les deux collections sont remplie etc...

    denière question et après je laisse aussi :
    dans la méthode send, ne faut-il pas utiliser un CopyOnWriteArrayList ? par mesure de sécurité

    sinon merci de ton aide

  13. #13
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    Je me rends compte que j'ai oublié de mettre des accesseur sur _messageInQueue et l'autre. Donc tu ajoutes ces méthodes dans MessageInOut:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public  void addMessageIn(MessageIn messageIn){ _serverReference._messageInQueue.add(messageIn);}
    et
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public  void addMessageOut(MessageIn messageOut){ _serverReference._messageOutQueue.add(messageOut);}
    Il faut aussi que tu ajoutes une reference du serveur dans Client en y écrivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    private Server _serverReference;
    et en modifiant le constructeur comme cela:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Client(Socket socket,Server server)
    	{
    		_groupName = null;
    		_socket = socket;
                    _serverReference=server;
    		try
    		{
    			_inputStream = _socket.getInputStream();
    			_outputStream = _socket.getOutputStream();
    		}
    		catch(Exception e) {e.printStackTrace();}
    	}
    Et dans serveur tu mets _messageManager en public (j'aurai dû tout mettre n public).

    Donc dans le run() de la classe Client, dés que tu reçois un message, il faut créer un objet MessageIn et le mettre dans la pile _messageInQueue en faisant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    _serverReference._messageManager.addMessageIn(messageIn);

    Et le Thread de classe MessageInOut le traitera comme il le faut.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    denière question et après je laisse aussi :
    dans la méthode send, ne faut-il pas utiliser un CopyOnWriteArrayList ? par mesure de sécurité
    Non, justement la façon dont tu cette méthode gère les messages grâce à des queues permet de ne rien avoir à synchroniser puisque tout passe par des structures du type ConcurrentLinkedQueue qui sont Thread-safe.

    Voilà c'est un peu le bordel, je fais ça à l'arrache

  14. #14
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut
    Justement je ne comprend pas, je bloque sur certain point.
    En effet nous pouvons avoir :

    - appel de MessageOut messageOut = _messageOutQueue.poll(); pour retirer le message.

    - appel de treatMessageOut( messageOut ). et là nous allons appelé messageOut.send().

    - Donc ici, nous allons parcourir ArrayList des clients afin de leurs envoyer des messages. Mais au même moment des clients peuvent se connecter et déconnecter donc l'ArrayList n'est plus valide ?


    Sinon merci, j'ai compris le principe...

  15. #15
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    Ouai exact. En fait, le code que j'ai fait donne juste le principe
    Si un client se ferme "brutalement", tu le saura dans le bloc catch de la méthode run du Thread Client. A partir de là, suffit de poster un MessageIn "interne" dans _messageOutQueue qui dit que tel client s'est deconnecté et qu'il faut le supprimer.
    Si jamais le Thread de MessageInOut doit envoyer un MessageOut à ce client déconnecté avant qu'il ne reçoive ce message de deconnection, ok il y aura une exception de levée.
    Ca tu peux pas l'en empêcher, mais ça n'est pas un problème puisque l'erreur sera ignorer dans un bloc try & catch de la methode send que tu peux rajouter.

    Si un client se connecte, pareil , il suffit de poster un message "interne" MessageIn pour mettre à jour la liste.

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Février 2007
    Messages
    382
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : France

    Informations forums :
    Inscription : Février 2007
    Messages : 382
    Par défaut
    Ah d'accord, je viens de comprendre ce que tu voulais faire.
    Je n'étais pas sur la même longueur que toi . Moi je voulais faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    try
    {
      while(true)
      {
     
      }
    }
    catch( Exception e )
    {
       server.removeClient( this );
    }
    alors que toi tu fait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    try
    {
      while(true)
      {
     
      }
    }
    catch( Exception e )
    {
      messageInOut.addMessageIn( messageInDeconnection ); 
    }
    merci beaucoup. Tout est bon.

  17. #17
    Membre éclairé Avatar de orelero
    Étudiant
    Inscrit en
    Novembre 2004
    Messages
    389
    Détails du profil
    Informations personnelles :
    Âge : 42

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2004
    Messages : 389
    Par défaut
    Ouaip c'est Ok .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [EJB3] ConcurrentModificationException collection list multi-thread jboss
    Par gudepier42 dans le forum Java EE
    Réponses: 1
    Dernier message: 10/05/2010, 13h09
  2. Tri multi-threadé
    Par Tifauv' dans le forum C
    Réponses: 8
    Dernier message: 28/06/2007, 09h00
  3. Réponses: 16
    Dernier message: 30/01/2004, 11h05
  4. [VB6][active x] faire du multi-thread avec vb
    Par pecheur dans le forum VB 6 et antérieur
    Réponses: 9
    Dernier message: 20/05/2003, 12h01
  5. [Kylix] exception qtinft.dll et multi-threading
    Par leclaudio25 dans le forum EDI
    Réponses: 3
    Dernier message: 27/03/2003, 18h09

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