写入输出流时套接字关闭?



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

堆栈跟踪:

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()时,身份验证阶段会出现异常。

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

编辑:我可能发现了这个问题。 我在写入输出流时使用资源尝试,我只是意识到尝试资源可以让输出流关闭,这要归功于@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:通过关闭输出流的一端修复了编辑 1 中的问题。

错误很清楚Socket is closed,可能有助于解决此异常的问题:

  • 确保未在客户端使用socket.close();
  • 您不会关闭任何输入或输出流,甚至不会关闭输入/输出,就像从文档中一样
关闭

返回的输入流将关闭关联的套接字。

关闭返回的输出流将关闭关联的套接字。

  • 您的连接不会超时。
  • 您的计算机中确实有有效的 TCP 连接。

编辑:java.net.SocketException: Connection reset通常意味着流的一端是关闭的,你自己说的

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

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

socket.setKeepAlive(true);

希望事情对你有用。

最新更新