Проблемы с копированием и записью IOUtils

#java #client-server

#java #клиент-сервер

Вопрос:

Я пытаюсь отправить строки на сервер с клиента, но, похоже, он не считывает данные из входного потока.

Клиент

 Scanner scanner = new Scanner(System.in);
Socket connection = new Socket("localhost", 13)
OutputStream out = connection.getOutputStream();

while(true) {
    String message = scanner.nextLine();
    IOUtils.write(message, out, "UTF-8");
    out.flush();
}
  

Сервер

 ServerSocket server = new ServerSocket(localhost,13);~
Socket connection = server.accept();
InputStream in = connection.getInputStream();
StringWriter writer = new StringWriter();

while(true) {
    try {
        IOUtils.copy(in, writer);
        System.out.println(writer.toString());
    } catch(IOException io) {}
}
  

Он считывает, если я закрываю поток из outputstream клиента, но я пытаюсь отправить несколько сообщений от клиента на сервер. Может кто-нибудь, пожалуйста, помогите

Ответ №1:

Вы, кажется, думаете, что каждый раз, когда вы вызываете flush() на стороне клиента, сервер узнает об этом и сможет узнать, что это конец сообщения. Это не так. IOUtils.copy() считывает все из потока байтов. Пока конец потока не достигнут, copy() он не вернется.

Вы можете видеть потоки как две стороны длинной трубы. Если вы нальете 10 ведер воды в конец трубки, все, что вы получите на другой стороне, — это непрерывный поток воды.

Если вам нужно несколько отдельных сообщений, вам необходимо разработать протокол, позволяющий разделять сообщения, и читать до тех пор, пока не будет достигнут конец сообщения. Например, это может быть основано на разделителях. Или вы можете отправить длину сообщения, за которой следует само сообщение, чтобы сервер знал, сколько байтов он должен прочитать, чтобы получить следующее сообщение.

Комментарии:

1. OP хочет отправить строки, где каждая строка является сообщением. Итак, протокол прост: используйте метод println println на стороне клиента для записи строк и используйте метод readLine() BufferedReader на стороне сервера для чтения строк. В этом случае концом сообщения является EOL, отправленный автором и обнаруженный методом readLine(). Вы должны разобраться с этим самостоятельно. Так вы научитесь.

2. Я только что обновил свой комментарий выше, объяснив, как это сделать.