Ubuntu下使用Protocol Buffer(简写:protobuf) (1.2编码)

1.2protobuf编码规则

1.2.1先了解varints编码

以300为例:1010 1100 0000 0010,这串数字是怎么来的呢?

1.首先删除每个字节的msb位,得到每7位为一组的数字:

1010 1100 0000 0010

  010 1100    000 0010

2.反转两组7位,再相连++

010 1100 000 0010

000 0010 ++ 010 1100 (反转两组7位,再相连++)

100101100 (300的二进制码)

-> 256+32+8+4=300

一个protobuf message是一系列的key-value对,key可以看成一个Tag。当对消息进行编码时,key和value被串联到一个字节流中。对message进行解码时,解析器需要能够跳过无法识别的字段。

Key (Tag)

Value

 

在流message中每一个key都是varint编码的值,格式:(field_number<<3)|wire_type。数字的最后3bit存储the wire type,

 

Ubuntu下使用Protocol Buffer(简写:protobuf) (1.2编码)

                                                                     Tag编码格式

Ubuntu下使用Protocol Buffer(简写:protobuf) (1.2编码)

                                                                                               编码结构图

每个field具有两种格式:

1.Tag-Length-Value :对应Type 2类型 Length-delimited

2. Tag-Value : 对应Type 1类型 int32, int64, uint32

编码与解码过程

例1:

在message中

int32 val =666;

原码:101 0011010

补码:101 0011010 (正数的补码=原码,负数的补码= 原码按位取反,再+1)

编码过程:

对补码101 0011010 从后向前取7位一组,并反转排序,得:

0011010 0000101

 

在加上msb,得

1 0011010 0 0000101(0x9a 0x05)

 

解码过程:先得到编码的结果为1 0011010 0 0000101(0x9a 0x05)

这里的第一个字节 msb = 1,所以需要再读一个字节,第二个字节的 msb = 0,则读取两个字节后停止。读到两个字节后先去掉两个 msb,剩下:

0011010 0000101

将这两个7-bit组反转得到补码:

0000101 0011010

将补码还原成原码,得:

666

 

例2:08(以去除msb位)

000 1000

 

例如:

96 01 = 1001 0110 0000 0001

→ 000 0001++ 001 0110 (先去掉msb位,再反转7位,在相连)

→ 10010110

→ 128+16+4+2=150