Protocol Buffer
发表于:2026-03-15 | 分类: techcommon
字数统计: 387 | 阅读时长: 1分钟 | 阅读量:

一种工业级结构化数据序列化方案,特性:跨语言、跨平台、体积小、版本兼容。

编码

核心:wire 格式。

消息示例:

1
2
3
message Test1 {
int32 a = 1; // 若a的值为5,只占用3byte:08 96 01
}

从bytes导出数据内容工具:https://github.com/protocolbuffers/protoscope/tree/main/testdata

1
2
// 导出结果
1:150

接下来揭秘该工具如何知道消息内容的(即解码)。

Base 128 Varints

varints,即变长整数,是wire格式的核心。允许1-10byte来编码无符号64bit整数,对于较小值使用较少字节。

1
2
3
4
5
6
// 1:占用1byte0000 0001
^ msb

// 150:占用2byte
10010110 00000001
^ msb ^ msb

如何计算得出150的?

1
2
3
4
5
10010110 00000001        // 原始输入
0010110 0000001 // 删除MSB
0000001 0010110 // 转换为大端序
00000010010110 // 拼接.
128 + 16 + 4 + 2 = 150 // 解释为无符号64位整数

消息结构

消息是键值对,消息二进制只使用字段编号作为key,因此字段名称无法解码得出。

编码时,每个kv都会转换为一条记录,其中包含:字段编号、wire类型、数据负载。wire类型标识了数据负载的大小,即Tag-Length-Value TLV方案。

wire类型:一共6种。

ID 类型 用于
0 VARINT int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 I64 fixed64, sfixed64, double
2 LEN string, bytes, embedded messages, packed repeated fields
3 SGROUP group start (弃用)
4 EGROUP group end (弃用)
5 I32 fixed32, sfixed32, float

Tag编码:(field_number << 3) | wire_type 的变长整数,即解码时低3bit表示wire类型,其余表示字段号

回到之前的示例:

1
2
// 值1:wiretype=000 field_number=0001
000 1000
上一篇:
Hello World
下一篇:
Agent