Сокет закрыт при записи в выходной поток? - PullRequest
0 голосов
/ 03 июля 2018

Почему сокет закрывается при попытке записи в выходной поток?

Трассировка стека:

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

Edit: Я мог бы найти проблему. Я использую попытку с ресурсами при записи в OutputStream, и я просто понимаю, что попытка с ресурсами позволяет закрывать 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, закрывая один конец выходного потока.

1 Ответ

0 голосов
/ 03 июля 2018

ошибка довольно ясна Socket is closed, вещи, которые могут помочь устранить это исключение:

  • Убедитесь, что вы не используете socket.close(); на стороне клиента.
  • Вы не закрываете ни один из входных или выходных потоков и даже не закрываете ввод / вывод, как в документах

Закрытие возвращенного InputStream закроет связанный сокет.

Закрытие возвращенного OutputStream закроет связанный сокет.

  • Ваше соединение не получает тайм-аут.
  • У вас есть действующее TCP-соединение на вашем компьютере.

Edit: java.net.SocketException: Connection reset обычно означает, что один конец потока закрыт, что вы сказали, что сами

Исправлена ​​ошибка в Edit 1, закрыв один конец выходного потока.

Оставьте выходной поток открытым, и вам, возможно, придется добавить:

socket.setKeepAlive(true);

надеюсь, у вас все получится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...