编码

参考:消息二进制格式

本文档描述了协议缓冲区消息的二进制 wire 格式。你不需要了解这个来在你的应用程序中使用协议缓冲区,但是了解不同的协议缓冲区格式如何影响你的编码信息的大小是非常有用的。

简单消息

假设你有以下非常简单的消息定义。

message Test1 {
  optional int32 a = 1;
}

在一个应用程序中,你创建了一个 Test1 消息并将 a 设置为 150。然后你将消息序列化到一个输出流。如果你能够检查编码后的消息,你会看到三个字节。

08 96 01

到目前为止,这么小的数字 - 但它意味着什么呢?继续阅读…

Base 128 Varints

为了理解你的简单协议缓冲区编码,你首先需要理解 varints。Varints 是一种使用一个或多个字节来序列化整数的方法。较小的数字需要较少的字节数。

除了最后一个字节外,varint中的每个字节都设置了最有意义的位(most significant bit,msb)—— 这表明还有更多的字节要来。每个字节的低 7 位用于存储数字的二补表示,以 7 位为一组,最小有效位在前。

因此,例如,这里是数字 1 - 这是一个单字节,所以 msb 没有设置:

0000 0001

而这里是 300 ——这有点复杂:

1010 1100 0000 0010

你如何计算出这是 300 呢?首先,你去掉每个字节的 msb,因为这只是为了告诉我们是否已经到达了数字的末尾(正如你所看到的,它被设置在第一个字节,因为 varint 中不止一个字节)。

 1010 1100 0000 0010
→ 010 1100  000 0010

你把两组 7 位倒过来,因为正如你所记得的,VARINTS 存储数字时,先存储最不重要的一组。然后你把它们连接起来,得到你的最终值。

000 0010  010 1100
→  000 0010 ++ 010 1100
→  100101100
→  256 + 32 + 8 + 4 = 300

消息结构