Входной поток сокетов непрерывно возвращает ноль в readLine, когда клиент отключен IntelliJ - PullRequest
0 голосов
/ 03 октября 2019

У меня есть простой TCP-сервер:

public class ServerSocketRunner {

  public static void main(String[] args) throws Exception {
    ServerSocket serverSocket = new ServerSocket(9000);

    while (true) {
      Socket socket = serverSocket.accept();

      new Thread(() -> {
        System.out.println("New client connected");
        try (PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));) {

          String inputLine, outputLine;
          do {
            inputLine = in.readLine();
            System.out.print("Received: " + inputLine);
            String serverResponse = "Message Received: " + now();
            System.out.println("Sending: " + serverResponse);
            out.println(serverResponse);
          } while (!"bye".equals(inputLine));

          socket.close();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }).start();
    }
  }
}

и клиент

public class ClientRunner {

  public static void main(String[] args) throws Exception {
    try (Socket socket = new Socket("localhost", 9000);
        Scanner input = new Scanner(socket.getInputStream());
        PrintWriter output = new PrintWriter(socket.getOutputStream(), true)) {

      Scanner userEntry = new Scanner(System.in);
      String message, response;
      do {
        System.out.print("Enter message: ");
        message = userEntry.nextLine();
        output.println(message);
        response = input.nextLine();
        System.out.println("\nSERVER> " + response);
      } while (!message.equals("bye"));
    }
  }
}

Клиент отправляет сообщения, которые пользователь вводит, сервер отвечает «Сообщение получено» и отметка времени. Все работает хорошо, кроме одного сценария. Если я закрою клиент с помощью IntelliJ, закройте, а затем кнопку «Отключить»

enter image description here

, сервер readLine непрерывно возвращает null и печатает

Received: nullSending: Message Received: 2019-10-03T14:44:36.962
Received: nullSending: Message Received: 2019-10-03T14:44:36.962
Received: nullSending: Message Received: 2019-10-03T14:44:36.962
...

Объяснение поведения IntelliJ отключение объясняется здесь

Отключение (если доступно) ---> Если выбрана эта опция,рабочий процесс отключен.

Таким образом, это будет означать, что отключение поддерживает процесс, но IntelliJ больше не будет к нему подключен. Тем не менее, это не объясняет, почему readLine постоянно возвращает null.

Кто-нибудь может объяснить это поведение?

1 Ответ

2 голосов
/ 04 октября 2019

Клиент был отключен, поэтому соединение между клиентом и сервером было разорвано. Но ваш код не обрабатывает это. Когда соединение разрывается, это составляет «конец потока», и функция BufferedReader 'readLine возвращает null. И это именно то, что он говорит вам в выводе:

Received: null [...]

Вам нужно проверить возвращаемое значение null и выйти из цикла.

    inputLine = in.readLine();
    if (inputLine == null) {
        System.out.print("Client disconnected. Leaving\n");
        break;
    }

И клиент, иСервер должен сделать этот тест. В реальной сети вы никогда не узнаете, когда ваш одноранговый узел исчезнет.

См. Документацию по https://docs.oracle.com/javase/8/docs/api/java/io/BufferedReader.html#readLine-- ( Возвращает: ... или ноль, еслидостигнут конец потока )

(я точно не знаю, что здесь происходит в IntelliJ, но очевидно, что серверный поток все еще работает. Сервер и клиент, предположительно, работают в отдельных подпрограммах). процессы или темы.)

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