高效的序列化、反序列化工具——ProtoBuf
目录
ProtoBuf 简介
ProtoBuf(Protocol Buffers) 是 Google 用于实现序列化与反序列化的开源项目,支持多语言、跨平台、可扩展的用于结构化数据的解决方案。
目前常见的序列化、反序列化方法包括但不限于以下几种:
- JSON
- XML
- ProtoBuf
- Boost Serialization
ProtoBuf 数据结构
| proto文件消息类型 | C++ 类型 | 说明 |
|---|---|---|
| double | double | 双精度浮点型 |
| float | float | 单精度浮点型 |
| int32 | int32 | 使用可变长编码方式,负数时不够高效,应该使用sint32 |
| int64 | int64 | 同上 |
| uint32 | uint32 | 使用可变长编码方式 |
| uint64 | uint64 | 同上 |
| sint32 | int32 | 使用可变长编码方式,有符号的整型值,负数编码时比通常的int32高效 |
| sint64 | sint64 | 同上 |
| fixed32 | uint32 | 总是4个字节,如果数值总是比2^28大的话,这个类型会比uint32高效 |
| fixed64 | uint64 | 总是8个字节,如果数值总是比2^56大的话,这个类型会比uint64高效 |
| sfixed32 | int32 | 总是4个字节 |
| sfixed64 | int64 | 总是8个字节 |
| bool | bool | |
| string | string | 一个字符串必须是utf-8编码或者7-bit的ascii编码的文本 |
| bytes | string | 可能包含任意顺序的字节数据 |
.proto 文件
| 关键字 | 说明 |
|---|---|
| syntax | 指定proto语言版本 |
| option | 修改配置选项 |
| service | 声明一个服务 |
| rpc | 声明一个方法 |
| resturns | 方法的返回值 |
| message | 定义一个消息类型 |
| repeated | 数组 |
| stream | 用流来交互 |
一些例子
指定一个版本
|
|
定义一个服务和方法
|
|
ProtoBuf使用一般步骤
1. 定义proto文件
proto文件中就是定义了我们需要存储或传输的数据结构/传输协议
proto文件的定义主要分为两部分:
- 为每一个需要序列化的数据结构添加一个消息(message)。
- 为消息(message)中的每一个字段(field)指定一个名字、类型和修饰符以及唯一标识(tag)。
其中每一个消息对应到C++就是一个类,嵌套消息对应的就是嵌套类。
另外,一个proto文件中可以定义多个消息,就像一个头文件中可以定义多个类一样。
|
|
- package 声明:
.proto文件以一个package声明开始,这个声明是为了防止不同项目之间的命名冲突,对应到 c++ 中,这个 .proto 文件生成的类将被放置在一个与package名相同的命名空间中。 - 字段类型:定义 message 时候,一个 message 就是某些类型字段的集合。具体支持的字段类型见:字段类型
- 修饰符:每个字段都必须用以下之一的修饰符来修饰:
修饰符 含义 required 必须提供字段值,否则对应的消息会被认为是" 未初始化“的。
注意:解析"未初始化"的消息会导致失败。optional 字段值指定与否都可以,它是每个字段默认值。
调用时候没有指定message的字段值,会自动使用默认值:string默认值是空字符串;int默认值是0repeated 字段会重复 N次(N可以是0),重复值的顺序会被保存在ProtoBuf中
注意:可以把重复字段视为数组。 - 唯一编号:每个消息中的每个字段都有唯一的编号,字段后边的
=1、=2等。这些字段编号用于标识消息二进制中的字段,并且在使用消息类型后不应该再更改。注意:1 ~ 15中的字段需要一个字节进行编码,包括字段编号和字段类型。16 ~ 2047中的字段编号需要两个字节。所以保留 1 - 15 作为非常频繁出现的消息元素,也要注意为将来可能频繁出现的消息元素预留位置。
可以指定的最小字段编号为:
1,最大字段编号:$2^{29}-1$ 或536 870 911。
也不能使用数字19 000到19 999,他们是 protobuf 保留的。
2. 编译proto文件
|
|
其中:
--cpp_out=<dir>表示生成代码输出到的指定文件夹-I<dir>表示在哪个文件夹下寻找 xxx.proto 文件xxx.proto就是我们写好的.proto文件
注意:如果编译上述例子出错,则可以重新编译安装 protobuf,几乎没有依赖,克隆源码就可编译安装。
亲测我的archlinux使用包管理器安装的 protobuf 是不能用的。
编译 protobuf 源码具体步骤如下:
- 克隆源码:https://github.com/protocolbuffers/protobuf.git
- 进入源码目录执行安装:
./autogen.sh && ./configure --prefix=/usr && make -j8 && sudo make install
3. 使用生成的代码来读写消息
|
|
序列化与反序列化过程中尽量保证使用
char*或std::string来接收数据。
亲测QString参与会导致反序列化失败。