目录
一、作用
Protocol Buffers 是 Google 的⼀种语⾔⽆关、平台⽆关、可扩展的序列化结构数据的⽅法,它可⽤于(数据)通信协议、数据存储等。你可以定义数据的结构,然后使⽤特殊⽣成的源代码轻松的在各种数据流中使⽤各种语⾔进⾏编写和读取结构数据。你甚⾄可以更新数据结构,⽽不破坏由旧数据结构编译的已部署程序。
二、使用
使用特点:Protobuf是需要依赖通过编译生成的头文件和源文件来使用的
1. 编写 .proto ⽂件,⽬的是为了定义结构对象(message)及属性内容。2. 使⽤ protoc 编译器编译 .proto ⽂件,⽣成⼀系列接⼝代码,存放在新⽣成头⽂件和源⽂件中。编译语法:proto [-I 目录](搜索我们要编译的文件在哪个目录下) --cpp_out=.(将编译好的文件放在哪个目录下) 编译文件名proto --cpp_out=. xxx.proto![]()
3. 依赖⽣成的接⼝,将编译⽣成的头⽂件包含进我们的代码中,实现对 .proto ⽂件中定义的字段进⾏设置set和获取get(一般省略get,直接写字段名),和对 message 对象进⾏序列化和反序列化。总的来说:ProtoBuf 是需要依赖通过编译⽣成的头⽂件和源⽂件来使⽤的。
proto文件:
syntax定义你使用的语法
package定义你的块名,防止多个proto文件编译时出错
message相当于class定义你所需的字段,字段编号从一开始,不能省略,不能重复
syntax = "proto3";
package phone;
// Phone represents a phone number with multiple numbers.
message Phone{
string number = 1;
}
三、proto3语法
Protocol Buffers 语⾔版本3,简称 proto3,是 .proto ⽂件最新的语法版本。proto3 简化了 Protocol Buffers 语⾔,既易于使⽤,⼜可以在更⼴泛的编程语⾔中使⽤。它允许你使⽤ Java,C++,Python 等多种语⾔⽣成 protocol buffer 代码。
3.1字段规则
singular:消息中可以包含该字段零次或⼀次(不超过⼀次)。 proto3 语法中,字段默认使⽤该规则。
repeated:消息中可以包含该字段任意多次(包括零次),其中重复值的顺序会被保留。可以理解为定义了⼀个数组
3.2消息类型的定义与使用
在一个proto文件中可以嵌套定义message
使用import引入其他proto文件进行字段调用
3.2查看二进制文件
一、hexdump将二进制文件转为ASCII,十六进制
hexdump -C *.bin
二、
protoc --decode=contacts.Contacts contacts.proto < contacts.bin
四、字段类型
4.1enum
1 enum PhoneType {
2 MP = 0; // 移动电话
3 TEL = 1; // 固定电话
4 }
定义规则:
1. 0 值常量必须存在,且要作为第⼀个元素 。这是为了与 proto2 的语义兼容:第⼀个元素作为默认值,且值为 0。2. 枚举类型可以在消息外定义,也可以在消息体内定义(嵌套)。3. 枚举的常量值在 32 位整数的范围内。但因负值⽆效因⽽不建议使⽤(与编码规则有关)
4.2any
字段还可以声明为 Any 类型,可以理解为泛型类型。使⽤时可以在 Any 中存储任意消息类型。Any 类型的字段也⽤ repeated 来修饰。
4.3oneof
如果消息中有很多可选字段, 并且将来同时只有⼀个字段会被设置, 那么就可以使⽤ oneof 加强这个⾏为,也能有节约内存的效果。
4.4map
语法⽀持创建⼀个关联映射字段,也就是可以使⽤ map 类型去声明字段类型,格式为:map<key_type, value_type> map_field = N;要注意的是:•key_type 是除了 float 和 bytes 类型以外的任意标量类型。 value_type 可以是任意类型。•map 字段不可以⽤ repeated 修饰•map 中存⼊的元素是⽆序的
4.5默认值

五、增删改规则
5.1新增
注意不要和老字段冲突!!!
5.2修改
(1)禁止修改任何已有的字段编号
(2)int32,uint32,int64,uint64与bool完全兼容,可转换;若类型不匹配,会采用与c++一致的处理方案(截断)
(3)sint32和sint64相互兼容,但不与其他整型兼容
(4)string和bytes在合法UTF-8字节前提下也兼容
(5)bytes包含消息编码版本的情况下,嵌套消息与bytes也兼容
(6)fixed32与sfixed32兼容
5.3删除
如果要删除老字段,要保证不使用已经被删除的或者已经被注释的字段编号,可使用reserved字段保留编号,保证以后其他字段无法使用该编号
六、未知字段
解析结构良好的protobuf已序列化数据中的未识别字段的表示方式
例如,当旧程序带有新字段的数据时,这些新字段就会成为旧程序的未知字段
七、前后兼容性
新老模块能正确识别两者间生成或发出的协议