Protocol Buffers(Protobuf )编码原理

🧱 一、Protobuf 的基本编码结构

Protobuf 的每个字段由三部分组成:

| Tag(字段编号 + 类型) | Length(长度,可选) | Value(值) |
  • Tag:由字段编号(field number)和 wire type(字段类型)组成。
  • Length:仅用于变长数据(如 string、bytes、嵌套消息)。
  • Value:字段的实际数据。

🔢 二、Wire Type(字段类型)

Protobuf 有 6 种 wire type(字段类型),它们用 3 位二进制表示,如下所示:

Wire Type(二进制)对应类型说明
000Varint可变长度整数,如 int32、int64、bool、enum
00164-bit固定8字节,如 double、fixed64
010Length-delimited变长数据,如 string、bytes、嵌套消息
011Start group已弃用
100End group已弃用
10132-bit固定4字节,如 float、fixed32

🔖 三、Tag 编码方式(字段编号 + wire type)

Tag 是字段编号(field number)和 wire type 的组合,使用 Varint 编码。

公式:

tag = (field_number << 3) | wire_type

例如:

  • 字段编号为 3,wire type 为 Length-delimited(即 010)
  • (3 << 3) = 24(即二进制 00011000
  • | 01000011010

所以最终 tag 的二进制是:00011010


🧮 四、Value 编码详解(使用二进制)

4.1 Varint 编码(Wire Type = 000)

Varint 是一种 变长整数编码方式,小数值占用更少字节。

规则

  • 每个字节的最高位(MSB)表示是否还有后续字节:
    • 1 表示继续读下一个字节
    • 0 表示结束
  • 低 7 位用于存储数据(小端方式)
示例:编码整数 1000
  1. 1000 的二进制是:1111101000
  2. 拆成 7 位一组(从低位开始):
    • 第一组:11101000(低 7 位)
    • 第二组:0000011(高 7 位)
  3. 加上 MSB:
    • 第一组:1 11101000
    • 第二组:0 0000011
  4. 最终二进制结果是:
    111101000 00000011
    

即两个字节:

  • 第一个字节:11110100
  • 第二个字节:00000011

4.2 Length-delimited 编码(Wire Type = 010)

用于编码字符串、嵌套消息等变长数据。

结构如下:

| Tag | Length (Varint) | Value (UTF-8 或嵌套消息) |
示例:字符串 “suc哈”
  • UTF-8 编码后是:
    • ‘s’ → 01110011
    • ‘u’ → 01110101
    • ‘c’ → 01100011
    • ‘哈’ → 11100101 10010011 10001000
  • 总长度为 6 字节
  • Length 为 6,Varint 编码为:00000110(因为小于 128,所以不加 MSB)
最终编码结构(二进制):
Tag:         00011010
Length:      00000110
Value ('s'): 01110011
Value ('u'): 01110101
Value ('c'): 01100011
Value ('哈'): 11100101 10010011 10001000

📦 五、完整示例(二进制展示)

假设我们有如下 .proto 定义:

message DemoRequest {
    optional string valueString = 3;
}

赋值:

valueString = "suc哈";

那么编码后的完整二进制序列如下:

00011010   // Tag: 3 + Length-delimited
00000110   // Length: 6
01110011   // 's'
01110101   // 'u'
01100011   // 'c'
11100101   // '哈' (UTF-8)
10010011
10001000

📊 六、总结对比(Protobuf vs JSON)

特性Protobuf(二进制)JSON(文本)
数据大小极小(字段名用编号代替)较大(包含字段名、引号等)
编码效率高(二进制操作)低(字符串解析)
可读性不可读可读
跨语言支持支持多种语言需要解析器
向后兼容性强(支持新增字段)弱(需手动处理兼容)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值