当前位置: 首页 > 知识库问答 >
问题:

Protobuf InvalidProtocolBufferException(带有一些字符串)

席俊达
2023-03-14

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

message 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”。

对于字符串

其中包含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个或更少的符号组成-没有问题。

共有1个答案

钱志强
2023-03-14

其中10是protobuf字段号,

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

198是字符串长度,1好像是字符串标识符,还是什么?

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

为什么protobuf不能解析这个消息呢?

我们需要看到其余的字节;如果没有所有的字节,库可能是非常正确的。您是否有所有的字节为失败的大小写,可能作为十六进制或基64?

 类似资料:
  • 我想打印如下内容: abc、def、ghi、JKL、mno、pqr 我刚写的时候: 所以我试着: 这给了我: abc、def、ghi、jkl、mno、pqr

  • 我对正则表达式很陌生。我需要构造一个正则表达式,如果在下面的代码中使用,它将生成一个只有字母(大小写)、数字、、、和。 以下表达式不起作用:。它替换了一些字母,而不是所有不需要的字符。为什么它不起作用?

  • 问题内容: 我想从我的字符串中删除以下所有字符 “> [],-” 目前我正在这样做。但必须有一个更有效的方法 问题答案: 使用描述要替换的所有字符的正则表达式,以及替换与该正则表达式匹配的所有内容的方法: (编辑:实际上,我认为不应该转义。而且我忘记了将反斜杠加倍,因为它们会被解释两次:一次是由Java编译器,一次是由正则表达式引擎。)

  • 问题内容: 我试图理解字符串比较与字符串比较的输出。需要明确的是,我拥有使用==和equals比较两个字符串的类。我试图将==和equals()的输出合并为字符串。equals()的输出会连续显示,但==的输出不会 连续显示。使用Java的装箱功能,将与字符串连接的布尔值联系起来。equals和==都返回布尔值。那么为什么会有这种差异呢?有人可以解释吗? 输出 更新:答案 如果不使用s1 == s

  • 问题内容: 我有这个: JSONLint表示这是完全有效的json。但是执行时出现错误。 但是,如果我将代码更改为: (请注意双反斜杠) 它可以工作,但是现在JSONLint表示。 有人可以帮助您了解这种行为吗? 问题答案: 有线格式和您必须在代码中编写的格式之间是有区别的。当您在代码中声明此代码时,您需要在文字中使用双-\,以便字符串获得一个反斜杠(否则,它将\\解释为一个转义序列,仅声明一个“

  • 具有以下json片段: 这是我的对象映射器配置 附加注意:Pojo类是使用jsonschema2pojo gradle插件生成的,并且基于json模式