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

Développement Web en Java Discussion :

Serveur multithread - Exception : java.util.ConcurrentModificationException


Sujet :

Développement Web en Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Par défaut Serveur multithread - Exception : java.util.ConcurrentModificationException
    Bonjour,

    Je suis entrain de faire un jeu de carte online, c'est la première fois que je me lance dans un programme en réseau avec multithread un peu plus pousser que de simple chat, etc...

    Il y a une application client et une serveur.

    Voici ce que je veux faire en ce moment :
    1) Le client entre son login
    2) La connection au serveur s'établie
    3) Le client envoie les données pour le login et le mot de passe
    4) Le serveur reçoit et va checker dans la base de donnée
    5) Si c'est bon il renvoie une confirmation positive au client sinon un rejet.
    6) Le client reçoit et affiche un message.

    De 1 à 4 tout va bien, mais quand le server doit aller envoyer la donnée de confirmation quelque chose de spécial se passe : le serveur recoit une nouvelle connexion de mon client et puisque je lui fait checker s'il est pas déjà connecté il va tout rejetter, ce qu'il ne devrait pas faire. Et ensuite il crash (le serveur)
    Citation Envoyé par Console serveur
    New connection !
    Number of thread : 2
    Packet receive : uno.Data@89ae9e
    class uno.Player
    New connection !
    Server has refused connection : 192.168.1.34 - Already connect
    Exception in thread "Thread-0" java.util.ConcurrentModificationException
    It didn't work! - Software caused connection abort: socket write error
    at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
    at java.util.AbstractList$Itr.next(AbstractList.java:343)
    at unoserver.Server$DaemonThread.run(Server.java:65)
    java.net.SocketException: Software caused connection abort: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
    at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1838)
    at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1747)
    at java.io.ObjectOutputStream.writeNonProxyDesc(ObjectOutputStream.java:1249)
    at java.io.ObjectOutputStream.writeClassDesc(ObjectOutputStream.java:1203)
    at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1387)
    thread interrupted
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1150)
    at java.io.ObjectOutputStream.writeFatalException(ObjectOutputStream.java:1538)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:329)
    at unoserver.Network.writeObject(Network.java:24)
    at unoserver.cmdToServer.acceptedConnect(cmdToServer.java:183)
    at unoserver.cmdToServer.getPlayerConnectServer(cmdToServer.java:172)
    at unoserver.cmdToServer.analyse(cmdToServer.java:75)
    at unoserver.Server$ServerData.run(Server.java:109)
    at java.lang.Thread.run(Thread.java:619)
    J'ai trouvé que cette erreur arrive si l'on n'utilise pas d'iterator pour parcourir une liste, donc c'est ce que j'ai fait mais l'erreur persiste.

    J'ai cherché pourquoi le serveur croit recevoir une nouvelle demande de connexion et je n'ai pas trouvé pourquoi. Le client ne se connecte qu'une seul fois je l'ai bien vérifié.

    Voici le code du serveur où il gère les threads :

    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
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
     
    package unoserver;
     
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.security.NoSuchAlgorithmException;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.Iterator;
    import java.util.List;
    import java.util.logging.Level;
    import java.util.logging.Logger;
     
    /**
     *
     * @author rxp
     */
    public class Server {
     
        // list of the inetaddress connected
    private List <InetAddress> address;
    // port of teh application
    private int port = 1991;
     
        public Server() throws IOException{
            //init
            address = new ArrayList<InetAddress>();
            Thread t = new DaemonThread();
     
      }
     
        class DaemonThread extends Thread{
            public DaemonThread(){
                //start the main thread
            start();
            }
     
            @Override
            public void run(){
     
            Socket skt = null;
            ServerSocket srvr = null;
                try {
                    //open the port
                    srvr = new ServerSocket(port);
                } catch (IOException ex) {
                    Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                }
     
            while(true){
                 try{
                     //accept the connections
                     skt = srvr.accept();
                     System.out.print("New connection ! \n");
                     //create an iterator of address
                     Iterator it = address.iterator();
                     //check in address if the client is already connected
                     while(it.hasNext()){
                         InetAddress add = (InetAddress) it.next();
                         if(skt.getInetAddress().equals(add)){
                             System.out.print("Server has refused connection : "+add.getHostAddress()+" - Already connect \n");
                             closeConnection(skt, false);
                         }else{
                         }
                     }
                     //error
                }catch(IOException ioe){
                     System.out.print("It didn't work! - "+ioe.getMessage()+"\n");
                     ioe.printStackTrace();
                     closeConnection(skt, false);
                }
                 //if no error :
                     // add the inetaddress to address
                 address.add(skt.getInetAddress());
                    // create the thread
                 Thread t = new Thread(new ServerData(skt));
                    // start the thread
                 t.start();
            }
     
            }
        }
     
     
      class ServerData implements Runnable{
          private Socket skt;
          Network network;
          cmdToServer cts = new cmdToServer();
          public ServerData(Socket skt){
              //init
              this.skt = skt;
              network = new Network();
              // number of thread
              System.out.println("Number of thread : "+Thread.activeCount());
          }
     
          public void run(){
     
          try{
                    try {
                        try {
                            //analyse the packet juste receive
                            cts.analyse((Object) network.readObject(skt), skt.getInetAddress());
                        } catch (SQLException ex) {
                            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                        } catch (NoSuchAlgorithmException ex) {
                            Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                        }
                    } catch (ClassNotFoundException ex) {
                        Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                    }
             }catch(IOException ioe){
                 //if error :
                 //close the connection
                System.out.print("It didn't work! - "+ioe.getMessage()+"\n");
                ioe.printStackTrace();
                    closeConnection(skt, true);
             }
          }
     
      }
     
      public void closeConnection(Socket skt, boolean thread){
        try {
            //remove address from address
                address.remove(skt.getInetAddress());
                //close the socket
                skt.close();
            } catch (IOException ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            }
            if(thread == true){
                //if want to :
                System.out.println("thread interrupted");
                //kill the thread
                Thread.currentThread().interrupt();
            }
     
      }
    La ligne erronée est sois-disant celle-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    InetAddress add = (InetAddress) it.next();

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par rXpCH Voir le message

    J'ai trouvé que cette erreur arrive si l'on n'utilise pas d'iterator pour parcourir une liste, donc c'est ce que j'ai fait mais l'erreur persiste.
    Non cette erreur se produit quand tu parcours une liste et que, en meme temps, sur un autre thread, tu la modifie. Il faut en multithread que tu code de manière à tenir compte des accès simultané, en protégeant tes ressources partagées contre l'utilisation concurentielle. Donc si tu lit ta liste, il faut mettre un verrou dessus tant que t'as pas fini de la lire, pour empecher un autre thread d'écrire dedans.

    Pour mettre ses verrous t'as le choix entre les blocs synchronized ou l'utilisation d'apis comme apache commons transaction.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Par défaut
    Je pense utiliser synchronized qu'en penses-tu ? Ca me permettrait de ne pas trop modifier mon code.

    Je n'ai jamais utilisé de synchronized, mais faut bien apprendre une fois si ça évite les threads de se bouffer entre eux. Merci pour voter aide je vous tiendrais au courant ici.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Par défaut
    Rebonjour,

    J'ai été me renseigner (Cours Java, FAQ Java et Forum Java par exemple :-°) j'ai vu que pour montrer que le block est synchronizer on ajoute synchronized à la déclaration de la méthode. Donc j'ai créé une méthode qui contient tout les check, supression et addition à la variable list : address. Mais le problème persiste (exactement le même).

    Voici la méthode :

    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
      public synchronized void makeConnectionsChanges(Socket skt, String type, boolean thread){
        if(type.equals("kill")){
          try {
            //remove address from address
                address.remove(skt.getInetAddress());
                //close the socket
                skt.close();
            } catch (IOException ex) {
                Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
            }
            if(thread == true){
                //if want to :
                System.out.println("thread interrupted");
                //kill the thread
                Thread.currentThread().interrupt();
            }
     
        }
        // create connection
        else if(type.equals("create")){
        // add the inetaddress to address
                 address.add(skt.getInetAddress());
                    // create the thread
                 Thread t = new Thread(new ServerData(skt));
                    // start the thread
                 t.start();
        }
     
        //check connection
        else if(type.equals("check")){
            //create an iterator of address
            Iterator it = address.iterator();
            while(it.hasNext()){
                         InetAddress add = (InetAddress) it.next();
                         if(skt.getInetAddress().equals(add)){
                             System.out.print("Server has refused connection : "+add.getHostAddress()+" - Already connect \n");
                             makeConnectionsChanges(skt, "kill", false);
                         }else{
                         }
                     }
     
        }
     
      }
    Avez-vous une idée ?

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    ce sont les changement mais aussi la lecture qui doivent etre synchronisé sur un objet commun. Rien ne sert de synchroniser les changement sur la lecture de la liste se fait sans protection.

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    165
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Décembre 2007
    Messages : 165
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    ce sont les changement mais aussi la lecture qui doivent etre synchronisé sur un objet commun. Rien ne sert de synchroniser les changement sur la lecture de la liste se fait sans protection.
    Désolé mais j'ai du mal à comprendre ^^ Ma list (address) doit elle être synchro, c'est cela ? Mais comment le faire ?

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

Discussions similaires

  1. [JDOM] Exception:Exception in thread "main" java.util.ConcurrentModificationException
    Par solawe dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 10/06/2009, 18h33
  2. Réponses: 3
    Dernier message: 12/04/2009, 18h39
  3. Réponses: 2
    Dernier message: 30/01/2009, 09h14
  4. Réponses: 5
    Dernier message: 02/06/2008, 12h21
  5. Exception java.util.PropertyPermission dans mon applet
    Par brunoperel dans le forum Applets
    Réponses: 3
    Dernier message: 11/05/2007, 10h32

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