2

我试图理解这里的协议缓冲区是示例,我无法理解的是字节在后续消息中的使用方式。我不知道这个号码 1 2 3是干什么用的。

message Point {
  required int32 x = 1;
  required int32 y = 2;
  optional string label = 3;
}

message Line {
  required Point start = 1;
  required Point end = 2;
  optional string label = 3;
}

message Polyline {
  repeated Point point = 1;
  optional string label = 2;
}

我在 google protobuf 中阅读了以下段落,但无法理解这里所说的内容,任何人都可以帮助我理解字节是如何用于存储信息的。

每个元素上的“= 1”、“= 2”标记标识该字段在二进制编码中使用的唯一“标签”。标签编号 1-15 比更高的编号需要少一个字节来编码,因此作为一种优化,您可以决定将这些标签用于常用或重复的元素,而将标签 16 和更高的标签用于不太常用的可选元素。

4

2 回答 2

4

protobuf 消息的一般形式是它是以下形式的对序列:

  • 字段头
  • 有效载荷

对于您的问题,我们可以在很大程度上忘记有效负载 - 这不是与 1/2/3 和 <=16 限制相关的位 - 所有这些都在字段标题中。字段头是一个“varint”编码的整数;“varint”使用最高有效位作为可选的延续位,因此较小的值(<=127,假设无符号而不是之字形)需要一个字节来编码 - 较大的值需要多个字节。或者换句话说,在需要设置延续位之前,您可以使用 7 个有用的位,至少需要 2 个字节。

然而!字段头本身由两部分组成:

  • 线型
  • 字段编号/“标签”

wire-type 是前 3 位,表示有效载荷的基本格式 - “length-delimited”、“64-bit”、“32-bit”、“varint”、“start-group”、“end-团体”。这意味着在我们拥有的 7 个有用位中,只剩下 4 个;4 位足以编码 <= 16 的数字。就是为什么建议您对最常见的元素使用字段编号 <= 16(作为优化)。

在您的问题中, 1 / 2 / 3 是字段编号;在编码时将其左移 3 并与有效载荷的线型组成;然后这个组合值是 varint 编码的。

于 2013-09-07T21:35:32.933 回答
1

Protobuf 将消息存储为从 id(他们称为标签的 =1、=2)到实际值的映射。这是为了能够更容易地扩展它,而不是像传输具有固定偏移量的结构那样传输数据。因此Point,例如,一条消息在高层次上看起来像这样:

1 -> 100,
2 -> 500

然后将其解释为x=100,y=500label=not set。在较低级别上,protobuf 以高度紧凑的格式序列化此标签值映射,其中包括以可变长度编码存储整数。您引用的段落只是在标签的情况下突出显示了这一点,如果它们 < 16,则可以更紧凑地存储,但例如对于 protobuf 定义中的整数值也是如此。

于 2013-09-07T19:37:15.177 回答