我正在使用Java聊天应用程序,到目前为止一切正常,除了当客户端断开连接并且其他客户端发送消息时,此错误会弹出:
java.net.SocketException: Software caused connection abort: socket write error
at java.base/java.net.SocketOutputStream.socketWrite0(Native Method)
at java.base/java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:110)
at java.base/java.net.SocketOutputStream.write(SocketOutputStream.java:150)
at java.base/java.io.DataOutputStream.write(DataOutputStream.java:107)
at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:401)
at java.base/java.io.DataOutputStream.writeUTF(DataOutputStream.java:323)
at com.terkea/com.terkea.system.server.ClientThread.run(ClientThread.java:65)
at java.base/java.lang.Thread.run(Thread.java:835)
这是我的服务器线程:
@Override
public void run() {
try {
DataInputStream in = new DataInputStream(socket.getInputStream());
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
while (!socket.isClosed()) {
try {
String input = in.readUTF();
if (Message.fromJSON(input).getUserName().equals("REGISTER")) {
Message specialMessage = Message.fromJSON(input);
specialMessage.setUserName("SERVER");
Client test = Client.fromJSON(specialMessage.getMessage());
test.setIp(socket.getInetAddress().toString());
test.setListening_port(String.valueOf(socket.getPort()));
specialMessage.setMessage(Client.toJSON(test));
input = Message.toJSON(specialMessage);
}
for (ClientThread thatClient : server.getClients()) {
DataOutputStream outputParticularClient = new DataOutputStream(thatClient.getSocket().getOutputStream());
outputParticularClient.writeUTF(input);
}
} catch (IOException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
和客户:
public void createClient() {
try {
socket = new Socket(getHost(), portNumber);
DataInputStream in = new DataInputStream(socket.getInputStream());
out = new DataOutputStream(socket.getOutputStream());
Message registerclient = new Message("REGISTER", Client.toJSON(getClient()));
out.writeUTF(Message.toJSON(registerclient));
new Thread(() -> {
while (!socket.isClosed()) {
try {
if (in.available() > 0) {
String input = in.readUTF();
Message inputMessage = Message.fromJSON(input);
if (inputMessage.getUserName().equals("SERVER")) {
System.err.println(Client.fromJSON(inputMessage.getMessage()));
allClientsConnected.add(Client.fromJSON(inputMessage.getMessage()));
} else {
chat.add(inputMessage);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
错误对应于outputParticularClient.writeUTF(input);
我的目标是摆脱此错误,并且如果可能的话,有人可以告诉我一种方法来检查客户端何时断开连接吗?我在这里发现了一些类似的问题,他们的解决方案是检查if (socket.getInputStream().read()!=-1)
但是当我这样做时,整个程序将冻结并且GUI停止工作。
答案 0 :(得分:1)
您可能想研究扩展特殊消息功能,而不是使用用户名传递“ REGISTER”,而是使用类似messageType
的名称。这样,您可以根据类型配置处理程序以执行许多操作。例如:
MessageType { REGISTER, UNREGISTER, READ_RECEIPT, ... }
然后您将拥有以下内容:
RegisterHandler {}
UnregisterHandler{}
并最终将它们扩展为具有一些功能,例如facebook / whatsapp(/ ICQ haha):
TypingHandler {} // Other user gets a message saying that I am typing to them
从这里,您可以实现UNREGISTER以执行您想要的操作。就像第一条评论所述,您应该捕获SocketException并手动注销该客户端,以使其不再发生。但您也应该尝试抢先发送
{
messageType: UNREGISTER,
from: Client1
to: server|null,
data: {}
}
,以便您的服务器可以在异常发生之前将其删除。如果您对此感兴趣,也可以使用它处理离线消息。