Protobuf InvalidProtocolBufferException с некоторыми строками - PullRequest
0 голосов
/ 17 мая 2018

Мы используем protobuf v.3 для передачи сообщений от клиента C # на сервер Java по HTTP.

Сообщение прото выглядит так:

message CLIENT_MESSAGE {
    string message = 1;
}

И клиент, и сервер используют кодировку символов UTF-8 для строк.

Все хорошо, когда мы используем короткие строковые значения, такие как "abc", но когда мы пытаемся передать строку с 198 символами в ней, мы ловим исключение:

   com.google.protobuf.InvalidProtocolBufferException: 
    While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.

Мы попытались сравнить даже байтовый массив, содержащий данные protobuf, и не нашли решения. Для байтового массива "aaa" строка начинается с следующих байтов:

10 3 97 97 97

Где 10 - номер поля protobuf, а 3 - длина строки, 69 65 67 - «ааа».

Для строки

"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

, который содержит 198 символов, байтовый массив начинается с этого:

10 198 1 97 97 97....

Где 10 - это номер поля protobuf, а 198 - длина строки, а 1 кажется идентификатором строки или как?

А почему protobuf не может разобрать это сообщение?

Уже потратил почти день на поиск решения этой проблемы, любая помощь приветствуется.

UPDATE:

Мы сделали дампы как с клиента, так и с сервера, и что странно - дампы разные!

Дамп Protobuf с клиента, перед отправкой на сервер:

00000000   0A C6 01 61 61 61 61 61  61 61 61 61 61 61 61 61   ·Æ·aaaaaaaaaaaaa
00000010   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000020   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000030   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000040   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000050   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000060   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000070   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000080   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00000090   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
000000A0   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
000000B0   61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
000000C0   61 61 61 61 61 61 61 61  61                        aaaaaaaaa  

Дамп Protobuf, который сервер получает:

0000: 0A EF BF BD 01 61 61 61 61 61 61 61 61 61 61 61   .....aaaaaaaaaaa
0010: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0020: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0030: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0040: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0050: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0060: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0070: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0080: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
0090: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00A0: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00B0: 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61 61   aaaaaaaaaaaaaaaa
00C0: 61 61 61 61 61 61 61 61 61 61 61                   aaaaaaaaaaa

Как вы можете видеть, заголовки данных protobuf различны ... Это совершенно не в моей голове, как это могло произойти?

UPDATE2: мы провели исследование и обнаружили, что эта проблема возникает только со строками, длина которых превышает 128 символов. Если строка состоит из 128 символов или меньше - проблем нет.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Ну, наконец, проблема заключалась в кодировке символов - мы попытались преобразовать двоичные данные protobuf в строку.

Если вам нужно передать двоичные данные protobuf в виде строки - сначала закодируйте их в base64 на клиенте, а затем декодируйте из base 64 на сервере.

Спасибо @Marc Gravell за помощь

0 голосов
/ 17 мая 2018

Где 10 - номер поля протобуфа,

Да;поле 1 с префиксом длины.

и 198 - длина строки, а 1 кажется идентификатором строки, или как?

198 1 - это строкадлина, закодированная с помощью "varint" кодирования;это вычисляется как целое число 198, но для кодирования требуется два байта.

И почему protobuf не может проанализировать это сообщение?

Нам нужно увидеть остальную частьбайт;библиотека может быть очень правильной, если у вас нет всех байтов.У вас есть все байтов для ошибочного регистра, возможно, в виде hex или base-64?

...