protobuf

Protobuf: Google Protocol Buffer,是 Google 公司内部的混合语言数据标准,用于 RPC 系统和持续数据存储系统。


proto3 与 proto2 的区别

proto3proto2 支持更多语言(如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
18
message 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
8
syntax = "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
3
make
./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
25
syntax = "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
2
python test_in.py 1.log
python test_out.py 1.log

李翔 wechat
微信交流
谢谢支持
0%