简体   繁体   English

客户端与服务器断开连接时,Java套接字写入错误

[英]Java socket write error when client disconnects from server

I am working on a chat app in Java and so far everything works all right except that when a client disconnects and a message is send by other client this error pops out: 我正在使用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)

This is my server Thread: 这是我的服务器线程:

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

and the Client: 和客户:

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

The error corresponds to outputParticularClient.writeUTF(input); 该错误对应于outputParticularClient.writeUTF(input);

My goal is to get rid of this error and also if possible could anybody tell me a way to check when a client disconnects? 我的目标是摆脱此错误,并且如果可能的话,有人可以告诉我一种方法来检查客户端何时断开连接吗? I've found some similar questions over here and their solution was to check if (socket.getInputStream().read()!=-1) but when I do that the whole program freezes and the GUI stops working. 我在这里发现了一些类似的问题,它们的解决方案是检查if (socket.getInputStream().read()!=-1)但是当我这样做时,整个程序将冻结并且GUI停止工作。

You may want to look into expanding upon your special message functionality, and instead of using the username to pass "REGISTER" use something like messageType in order to do so. 您可能需要研究扩展特殊消息功能,而不是使用用户名传递“ REGISTER”,而是使用诸如messageType之类的方法。 This way you can configure handlers based on type to do a number of things. 这样,您可以根据类型配置处理程序以执行许多操作。 For example things like: 例如:

MessageType { REGISTER, UNREGISTER, READ_RECEIPT, ... }

You can then have things like: 然后,您可以进行如下操作:

RegisterHandler {}
UnregisterHandler{}

and eventually expand them to have some features like facebook/whatsapp (/ICQ haha): 并最终将它们扩展为具有一些功能,例如facebook / whatsapp(/ ICQ haha​​):

TypingHandler {} // Other user gets a message saying that I am typing to them

From here, you can implement the UNREGISTER to do what you want. 从这里,您可以实现UNREGISTER来执行您想要的操作。 Like the first comment says, you should catch the SocketException and manually unregister that client so it doesn't happen anymore. 就像第一条评论所述,您应该捕获SocketException并手动注销该客户端,以使其不再发生。 But you should also try to pre-emptively send an 但您也应该尝试抢先发送

{
    messageType: UNREGISTER,
    from: Client1
    to: server|null,
    data: {}
 }

so that your server can remove it before the exception occurs. 这样您的服务器就可以在发生异常之前将其删除。 This would also let you handle Offline messages, if that's something you're interested in. 如果您对此感兴趣,也可以使用它处理脱机消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM