#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.
Кажется, что предпочтительным поведением является использование нового сокета для каждого сообщения. Для меня это звучит немного странно, но я уверен, что для этого есть веская причина. Однако это должно быть лучше объяснено в официальном руководстве.