Search code examples
javaeclipsetry-catchbreakpoints

Not catching Exception in server (unless I add a breakpoint)


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>());

Solution

  • 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(...));