Буферы протокола Google не читаются должным образом

#java #ubuntu #protocol-buffers

#java #ubuntu #буферы протокола

Вопрос:

Я просто настраиваю новый Java-проект, который (возможно, сейчас не уверен) будет использовать буферы протокола Google. Я новичок в этом API, поэтому я начал с очень простого теста. Тест, результат которого, честно говоря, действительно разочаровал меня. Почему этот очень простой код не работает?

 var output = new ByteArrayOutputStream();
Message.Echo.newBuilder().setMsg("MSG1?").build().writeTo(output);
System.out.println("output.length "   output.toByteArray().length);
Message.Echo.newBuilder().setMsg("MSG2!!").build().writeTo(output);
System.out.println("output.length "   output.toByteArray().length);

var input = new ByteArrayInputStream(output.toByteArray());
System.out.println("input.available "   input.available());
System.out.print(Message.Echo.parseFrom(input));
System.out.println("input.available "   input.available());
System.out.print(Message.Echo.parseFrom(input));
  

Приведенный выше код выдает следующий результат:

 output.length 7
output.length 15
input.available 15
msg: "MSG2!!"
input.available 0
  

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

Однако, изменив две строки чтения на:

 System.out.print(Message.Echo.parseFrom(input.readNBytes(7)));
System.out.print(Message.Echo.parseFrom(input.readNBytes(15-7)));
  

правильно печатает два сообщения. Я запускаю Kubuntu 18.04 с JDK 11. Я упускаю что-то действительно важное (не упомянутое в официальном руководстве) или это ошибка?

Это файл .proto:

 syntax = "proto3";

package ...;

option java_package = "...";
option java_outer_classname = "Message";

message Echo {
    string msg = 1;
}
  

Ответ №1:

Хорошо, кажется, что для записи / чтения нескольких сообщений с использованием одного и того же набора потоков требуется вместо этого использовать writeDelimitedTo и parseDelimitedFrom, потому что parseFrom читает до тех пор, пока не достигнет EOF.

Кажется, что предпочтительным поведением является использование нового сокета для каждого сообщения. Для меня это звучит немного странно, но я уверен, что для этого есть веская причина. Однако это должно быть лучше объяснено в официальном руководстве.