带有一些字符串的Protobuf InvalidProtocolBufferException

时间:2018-05-17 09:14:19

标签: protocol-buffers protobuf-csharp-port protobuf-java

我们使用protobuf v.3通过HTTP将消息从C#客户端传输到Java服务器。

消息proto看起来像这样:

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是" aaa"。

对于字符串

  

" aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

其中包含198个字符,字节数组以此开头:

10 198 1 97 97 97....

其中10是protobuf字段编号,198是字符串长度,1似乎是字符串标识符,或者是什么?

为什么protobuf无法解析此消息?

已经花了将近一天时间寻找这个问题的解决方案,感谢任何帮助。

更新

我们从客户端和服务器都进行了转储,这很奇怪 - 转储是不同的!

在发送到服务器之前,

来自客户端的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 :(得分:2)

嗯,最后问题是字符编码 - 我们试图将二进制protobuf数据转换为字符串。

如果您需要将二进制protobuf数据作为字符串传输 - 首先在客户端上将其编码为base64,然后在服务器上从base 64进行解码。

感谢@Marc Gravell寻求帮助

答案 1 :(得分:1)

  

其中10是protobuf字段编号,

是;字段1,长度为前缀。

  

和198是字符串长度,1似乎像字符串标识符,或什么?

198 1是字符串长度,用" varint"编码。编码;这计算为整数198,但需要两个字节进行编码。

  

为什么protobuf无法解析此消息?

我们需要查看剩下的字节;如果您没有所有字节,那么图书馆可能非常正确。你有所有失败案例的字节,可能是hex或base-64吗?