protobufs格式的原始解码器

时间:2011-09-08 06:16:38

标签: protocol-buffers

我想找到一种方法将二进制protobuf消息转换为包含数据的人类可读描述,而不使用.proto文件。

背景是我有一条.proto消息说它被Android上的解析器拒绝了,但是为什么并不完全清楚。我可以手工完成这个消息,但这很乏味。

我尝试protoc --decode_raw,但它只是给出错误“无法解析输入。”。我谷歌希望/期望有人会做一个很好的网络工具,可能会做到这一点,但没有找到任何明显的。

我只是希望获得一些输出:

field 1: varint: 128
field 4: string: "foo"

任何正确方向的指针都是最受欢迎的!

5 个答案:

答案 0 :(得分:28)

对于后人: Google的协议缓冲区tools可以解码原始缓冲区。

只需将未知缓冲区发送给它并传递--decode_raw标志

$ cat has_no_proto.buff | protoc --decode_raw
2 {
  2: "Error retrieving information from server. [RH-02]"
}

所以这是一条消息,其中字段2设置为嵌入消息,而消息又具有  它的第二个字段设置为一个字符串,告诉我我生气了Google Play。

类型信息不明确(看起来它会尝试将所有二进制数据显示为字符串 - 但是满足了对varint / string / submessage区别的要求。)

答案 1 :(得分:8)

正如Michel de Ruiter's answer中所述,您的protobuf消息可能有length-prefix。假设确实如此,这个答案应该会有所帮助。

(注意:对于下面的大多数命令,我假设您的protobuf消息存储在名为input的文件中。)

单个邮件的

protoc --decode_raw + dd

如果它只是一条消息,那么您确实可以利用protoc --decode_raw,但您需要先删除长度前缀标头。假设标题长度为4个字节,您可以使用ddinput中删除标题,然后将输出反馈到protoc

dd bs=1 skip=4 if=input 2>/dev/null | protoc --decode_raw
单个邮件的

protoc-decode-lenprefix --decode_raw

我还写了一个script来自动处理标题剥离:

protoc-decode-lenprefix --decode_raw < input

此脚本只是protoc --decode_raw之上的包装器,但处理解析长度前缀标头然后调用protoc

现在,在这种情况下,这个脚本并不是非常有用,因为我们可以使用上面的dd技巧来删除标题。但是,假设我们有一个数据流(例如,文件或TCP流),其中包含多个以长度前缀标题框起的消息....

protoc-decode-lenprefix --decode_raw表示消息流:

而不是输入文件中的单个protobuf消息,假设input包含多个protobuf消息,这些消息由长度前缀标头构成。在这种情况下,只是使用dd技巧是不可能的,因为您需要实际读取length-prefix标头的内容以确定流中后续消息的时长,因此,下一个标题+消息前面有多少字节。因此,您不必担心所有这些,只需再次使用protoc-decode-lenprefix

protoc-decode-lenprefix --decode_raw < input

protoc-decode-lenprefix --decode ... foo.proto用于消息流

此脚本还可用于完全解码长度前缀的消息(而不仅仅是&#34;原始解码&#34;它们)。它假定您可以访问定义protobuf消息的.proto文件,就像包装的protoc命令一样。调用语法与protoc --decode相同。例如,将dd技巧与protoc --decode一起使用,输入为Mesos task.info文件,语法如下所示:

dd bs=1 skip=4 if=task.info 2>/dev/null | \
protoc --decode mesos.internal.Task \
                      -I MESOS_CODE/src -I MESOS_CODE/include \
                      MESOS_CODE/src/messages/messages.proto

使用protoc-decode-lenprefix

时参数相同
cat task.info | \
protoc-decode-lenprefix --decode mesos.internal.Task \
                      -I MESOS_CODE/src -I MESOS_CODE/include \
                      MESOS_CODE/src/messages/messages.proto

答案 2 :(得分:7)

如果您碰巧有一个包含(多个?)长度前缀 protobuf消息的二进制文件,protoc ‒‒decode_raw < file由于长度前缀而无法解析它。一个简单的方法是将文件拆分为连续的消息,然后将每个消息转换为protoc

我的看法:

var fs = File.OpenRead(filename));
var buffer = new byte[4096];
int size;
for (int part = 1; Serializer.TryReadLengthPrefix(fs, PrefixStyle.Base128, out size); part++) {
  long startPosition = fs.Position;
  using (var writer = File.OpenWrite(string.Format("{0}[{1}].pb", filename, part))) {
    for (int bytesToRead = size; bytesToRead > 0; ) {
      int bytesRead = fs.Read(buffer, 0, Math.Min(bytesToRead, buffer.Length));
      bytesToRead -= bytesRead;
      if (bytesRead <= 0) // End of file.
        break;
      writer.Write(buffer, 0, bytesRead);
    }
  }
}

答案 3 :(得分:6)

您可以尝试强制通过wireshark插件,或者您可以借用某些实现的“读者”部分(例如,我知道如何在C#中执行此操作,但我怀疑这就是您的意思)。

但是,要小心 - 协议缓冲区中的字符串并不真正意味着“字符串” - 它可能是:

  • UTF-8字符串
  • 任意数据的原始BLOB
  • 子信息
  • 一个“打包”数组
  • (可能还有别的我忘了)

答案 4 :(得分:1)

也许试试https://pb-decode.online。我是作者,欢迎提出建议:)

enter image description here