所以基本上我有一个try / catch,我的catch捕获异常。目的是在客户端断开连接而不通知服务器的情况下从连接的客户端列表中删除客户端。出于某种原因虽然没有捕获。奇怪的是,当我在catch上添加断点时(我正在使用eclipse btw)它会中断,然后当我继续时,它会捕获并继续正常捕获,直到我重新启动服务器。此时所有客户端都会连接到服务器然后死掉。如果我尝试关闭服务器窗口,服务器不会捕获此然后停止响应。如果它没有捕获,阻止它的唯一方法是终止它。
因此,为了澄清我的代码是有效的,我的问题是单独捕获没有捕获导致服务器没有意识到客户端已离开服务器。添加断点会因某些原因而修复它,这是我的问题。
以下是服务器的大部分代码:
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 };
服务器断开连接方法:
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) {}
}
这是我在添加断点时遇到的异常(如果我不添加它就不会发生):
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)
因此,作为更新,如果我取消注释第103行,它也将起作用。 另外我在评论中提到我正在关注一个教程,这是我正在关注以供参考:http://www.youtube.com/watch?v=VFF0JRCFCH0
编辑:非常感谢azzurroverde,问题实际上是我的列表没有同步。 将第35-37行更改为以下修复了我的问题,它现在可以正常工作: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>());
答案 0 :(得分:0)
在经过长时间的讨论后,让我们总结一下答案:) 问题是ArrayList没有同步,不同的线程同时访问它,使其处于不稳定状态
public static ArrayList<Socket> list_sockets = new ArrayList<Socket>();
解决方案是同步数组列表: http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html
List list = Collections.synchronizedList(new ArrayList(...));