Protobuf: Google Protocol Buffer,是 Google 公司内部的混合语言数据标准,用于 RPC 系统和持续数据存储系统。
proto3 与 proto2 的区别
proto3 比 proto2 支持更多语言(如Go、Ruby、JavaNano等),去掉了一些复杂的语法和特性,更强调约定而弱化语法。下面列举几点 proto3 与 proto2 的不同点:
1、proto 文件开头第一行必须指定版本:syntax = "proto3";
,而在 proto2 中,可以写成 syntax = "proto2";
或者不写;
2、字段规则移除了 “required”,将并把 “optional” 改名为 “singular”;
3、“repeated” 字段默认采用 packed 编码,而在 proto2 中,需要明确使用 [packed=true] 来为字段指定比较紧凑的 packed 编码方式;
4、移除了 default 选项,在 proto2 中,可以使用 default 选项为某一字段指定默认值,而在 proto3 中,字段的默认值只能根据字段类型由系统决定;
5、增加了 JSON 映射特性
……
protobuf编程
由于我的开发环境是Ubuntu 1604, 所以我这里编写示例代码将使用 proto2。protobuf是支持嵌套类型的,如下所示为 Protocol Buffers 官方文档提供的嵌套类型示例 Protocol Buffers 官方文档(proto文件添加注释和C/C++一样,使用 //
或 /* ... */
语法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
示例代码将介绍两种语言的 protobuf 使用,C++和Python,对于C++,编译器会根据每个.proto文件生成一个.h和一个.cc文件,并为文件中描述的每种消息类型提供一个类。而对于Python则不同,Python编译器生成一个模块,其中包含每个消息类型的静态描述符,.proto然后与元类一起使用,以在运行时创建必要的Python数据访问类。
C++示例
在动手编写代码之前,我们需要先安装编译依赖,执行如下命令:
1
$ sudo apt install libprotobuf-dev protobuf-compiler
C++ 示例代码的myinfo.proto文件的内容如下:
1
2
3
4
5
6
7
8syntax = "proto2";
package com.xiaoming.protobuf;
message BufferMessage{
required int64 id = 1;
required string name = 2;
optional int32 opt = 3;
}
使用 protoc 命令根据 .proto 文件生成对应的 .pb.cc 和 .pb.h 文件,格式如下:
protoc -I=输入目录 --cpp_out=输出目录 xxx.proto
比如执行protoc -I=./ --cpp_out=./ myinfo.proto
则生成 myinfo.pb.cc 和 myinfo.pb.h。
源码中 test_in.c 的作用是序列化,并将序列化的内容写入文件中,而 test_out.c 的作用则是反序列化,读取 test_in.c 写入文件中的内容并反序列化。
具体编译情况见Makefile文件,编译和运行如下:
1
2
3make
./test_in
./test_out
Python示例
安装依赖,执行如下命令:
1
$ sudo apt install python-protobuf
Python 示例代码的myinfo.proto文件的内容如下(该文件根据上面提到的 Protocol Buffers 官方文档中提供的嵌套类型示例改写而来):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25syntax = "proto2";
package com.xiaoming.protobuf;
message ClassMate{
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber{
required string number = 1;
required PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AlumniBook{
repeated ClassMate mate = 1;
}
使用 protoc 命令根据 .proto 文件生成对应的 .py 文件,格式如下:
protoc -I=输入目录 --python_out=输出目录 xxx.proto
比如执行 protoc -I=./ --python_out=./ myinfo.proto
则生成 myinfo_pb2.py 文件。
源码中 test_in.py 的作用是序列化,并将序列化的内容写入文件中,test_out.py 的作用则是反序列化,读取 test_in.py 写入文件中的内容并反序列化。
运行命令如下:
1
2python test_in.py 1.log
python test_out.py 1.log