So basically I have a try/catch where my catch is catching Exception. The purpose is to remove a client from the list of connected clients if a client disconnects without notifying the server. For some reason though its not catching. The weird part is that when I add a breakpoint at the catch (i'm using eclipse btw) it breaks and then when i continue, it catches and will continue to catch properly until I restart the server. At this point all the client does is it connects to the server and then dies. The server doesn't catch this and then stops responding if I try and close the server window. The only way to stop it if it doesn't catch is to terminate it.
So to clarify my code works, my issue is the solely with the catch not catching which results in the server not realizing that the client has left the server. Adding a breakpoint fixes it for some reason which is my problem.
Here is most of the code for the server:
35 public static ArrayList<Socket> list_sockets = new ArrayList<Socket>();
36 public static ArrayList<Integer> list_client_states = new ArrayList<Integer>();
37 public static ArrayList<DataPackage> list_data = new ArrayList<DataPackage>();
38
39 private static Runnable accept = new Runnable() {
40 @Override
41 public void run() {
42 new Thread(send).start();
43 new Thread(receive).start();
44
45 while (true) {
46 try {
47 Socket socket = server.accept();
48
49 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
50
51 String username = (String) ois.readObject();
52
53 ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
54 oos.writeObject("Welcome...");
55
56 list_clients_model.addElement(username + " - " + socket.getInetAddress().getHostAddress() + " - " + socket.getInetAddress().getHostName());
57 list_client_states.add(0);
58
59 list_data.add(new DataPackage());
60 list_sockets.add(socket);
61 }
62 catch (Exception e) {}
63 }
64 }
65 };
66
67 private static Runnable send = new Runnable() {
68 @Override
69 public void run() {
70 ObjectOutputStream oos;
71
72 while (true) {
73 for (int i = 0; i < list_sockets.size(); i++){
74 try {
75 oos = new ObjectOutputStream(list_sockets.get(i).getOutputStream());
76 int client_state = list_client_states.get(i);
77 oos.writeObject(client_state);
78
79 oos = new ObjectOutputStream(list_sockets.get(i).getOutputStream());
80 oos.writeObject(list_data);
81
82 if (client_state == 1) { // Kicked by server
83 disconnectClient(i);
84 i--;
85 }
86 else if (client_state == 2) { // Server Disconnected
87 disconnectClient(i);
88 i--;
89 }
90 }
91 catch (Exception e) {}
92 }
93 }
94 }
95 };
96
97 private static Runnable receive = new Runnable() {
98 @Override
99 public void run() {
100 ObjectInputStream ois;
101
102 while (true) {
103 //System.out.println(list_sockets.size());
104 for (int i = 0; i < list_sockets.size(); i++) {
105 try {
106 ois = new ObjectInputStream(list_sockets.get(i).getInputStream());
107 int receive_state = (Integer) ois.readObject();
108
109 ois = new ObjectInputStream(list_sockets.get(i).getInputStream());
110 DataPackage dp = (DataPackage) ois.readObject();
111
112 list_data.set(i, dp);
113
114 if (receive_state == 1) { // Client disconnected by user
115 disconnectClient(i);
116 i--;
117 }
118 }
119 catch (Exception e) { // Client Disconnected (Client didn't notify server about disconnecting)
120 disconnectClient(i);
121 i--;
122 e.printStackTrace();
123
124 }
125 }
126 }
127 }
128 };
And the Server disconnect method:
public static void disconnectClient(int index) {
try {
list_clients_model.removeElementAt(index);
list_client_states.remove(index);
list_data.remove(index);
list_sockets.remove(index);
}
catch (Exception e) {}
}
Here is the exception I am getting when I add the breakpoint (it doesn't happen if I don't add it):
java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(Unknown Source)
at java.net.SocketInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.read(Unknown Source)
at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at ServerMain$3.run(ServerMain.java:105)
at java.lang.Thread.run(Unknown Source)
So as an update, it will also work if I uncomment line 103. Also I mentioned in the comments that I'm following a tutorial this is the on i'm following for reference: http://www.youtube.com/watch?v=VFF0JRCFCH0
EDIT: So thank you azzurroverde, the problem was in fact that my lists wern't synchronized. Changing lines 35-37 to the following fixed my issue and it now works fine:
35 public static List<Socket> list_sockets = Collections.synchronizedList(new ArrayList<Socket>());
36 public static List<Integer> list_client_states = Collections.synchronizedList(new ArrayList<Integer>());
37 public static List<DataPackage> list_data = Collections.synchronizedList(new ArrayList<DataPackage>());
Let's summarize the answer then, after this long discussion :) The problem was that the ArrayList was not synchronized and different threads were accessing it at the same time leaving it in an unstable state
public static ArrayList<Socket> list_sockets = new ArrayList<Socket>();
The solution was to synchronize the array list: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
List list = Collections.synchronizedList(new ArrayList(...));