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:
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:
InetAddress add = (InetAddress) it.next();