【问题标题】:Socket closed when writing to the output stream?写入输出流时套接字关闭?
【发布时间】:2018-12-11 15:52:35
【问题描述】:

当我尝试写入输出流时,为什么套接字会关闭?

堆栈跟踪:

Exception in thread "main" java.lang.RuntimeException: java.net.SocketException: Socket is closed
    at chatx.server.handler.ExceptionHandler.handle(ExceptionHandler.java:14)
    at chatx.server.handler.ExceptionHandler.handle(ExceptionHandler.java:6)
    at chatx.server.Client.authenticate(Client.java:75)
    at chatx.server.handler.SocketHandler.handle(SocketHandler.java:23)
    at chatx.server.handler.SocketHandler.handle(SocketHandler.java:12)
    at chatx.server.Server.listen(Server.java:117)
    at chatx.server.Server.start(Server.java:61)
    at chatx.server.Main.main(Main.java:30)
Caused by: java.net.SocketException: Socket is closed
    at java.base/java.net.Socket.getInputStream(Socket.java:905)
    at chatx.server.Client.authenticate(Client.java:65)
    ... 5 more

预认证阶段:

Client client = (Client) Optional.ofNullable(clientManager.getClient(socket.getInetAddress())).orElse(clientManager.addClient(new Client(socket)));
client.sendPacket(new PacketAuthentication(client.getUsername(), client.getPassword().toCharArray()));

if (client.authenticate()) {
    System.out.printf("[Address: %s] Authenticated as %s.\n", client.getAddress(), client.getName());
    client.start();
} else {
    client.interrupt();
    clientManager.removeClient(client);
    System.out.printf("[Address: %s] Failed to authenticate.\n", client.getAddress());
}

身份验证阶段:

try {
    JsonObject o = new GsonBuilder().create().fromJson(new String(socket.getInputStream().readAllBytes()), JsonObject.class);

    if (o.has("packet_id") && o.get("packet_id").getAsInt() == PacketAuthentication.ID) {
        JsonObject data = o.getAsJsonObject("data");
        String username = data.get("username").getAsString();
        String password = data.get("password").getAsString();

        return this.username.equals(username) && this.password.equals(password);
    }
} catch (IOException ex) {
    Server.getInstance().getExceptionHandler().handle(ex);
}

客户端身份验证阶段:

IClient client = new Client(new Socket("127.0.0.1", 8888));
client.sendPacket(new PacketAuthentication("Dummy", "Dummy123".toCharArray()));

在认证阶段调用socket.getInputStream()时发生异常。

这个想法是让客户端在登录时发送一个身份验证数据包并在服务器端验证信息。

供参考,我的 github 页面上有项目: https://github.com/Azoraqua/ChatX/tree/development

编辑: 我可能发现了这个问题。 我在写入 OutputStream 时使用了 try-with-resources,我只是意识到 try-with-resources 让 OutputStream 关​​闭,这要感谢@MousaHalaseh

但现在我又遇到了另一个关于“连接重置”的异常:

Exception in thread "main" java.lang.RuntimeException: java.net.SocketException: Connection reset
    at chatx.server.handler.ExceptionHandler.handle(ExceptionHandler.java:14)
    at chatx.server.handler.ExceptionHandler.handle(ExceptionHandler.java:6)
    at chatx.server.Client.authenticate(Client.java:86)
    at chatx.server.handler.SocketHandler.handle(SocketHandler.java:23)
    at chatx.server.handler.SocketHandler.handle(SocketHandler.java:12)
    at chatx.server.Server.listen(Server.java:117)
    at chatx.server.Server.start(Server.java:61)
    at chatx.server.Main.main(Main.java:28)
Caused by: java.net.SocketException: Connection reset
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:210)
    at java.base/java.net.SocketInputStream.read(SocketInputStream.java:141)
    at java.base/java.io.InputStream.readAllBytes(InputStream.java:238)
    at chatx.server.Client.authenticate(Client.java:76)
    ... 5 more

编辑 2: 通过关闭输出流的一端,修复了 Edit 1 中的问题。

【问题讨论】:

    标签: java sockets


    【解决方案1】:

    错误很明显Socket is closed,这可能有助于解决此异常:

    • 确保您没有在客户端使用socket.close();
    • 您没有关闭任何输入或输出流,甚至没有关闭输入/输出,就像来自 documents 的那样

    关闭返回的 InputStream 将关闭关联的套接字。

    关闭返回的 OutputStream 将关闭关联的套接字。

    • 您的连接不会超时。
    • 您的机器中确实有一个有效的 TCP 连接。

    编辑: java.net.SocketException: Connection reset一般表示流的一端是关闭的,你自己说的

    通过关闭输出流的一端,修复了编辑 1 中的问题。

    保持输出流打开,您可能需要添加:

    socket.setKeepAlive(true);
    

    希望事情对你有用。

    【讨论】:

    • 是的,我知道错误是什么。我不知道为什么错误是,我从来没有手动关闭过套接字。
    • 谢谢你,穆萨。我刚刚意识到可能是什么问题,我编辑了我的问题以反映实现。
    猜你喜欢
    • 1970-01-01
    • 2015-01-01
    • 2012-02-12
    • 2011-03-29
    • 2011-04-26
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多