Google Protocol Buffers 简称 Protobuf, 是Google公司内部的混合语言数据标准,提供了一种轻量高效的结构化数据存储。
为什么要使用protobuf呢?
- 灵活高效结构化数据存储格式(.proto),便于序列化适合RPC的数据交换。
- 与XML相比更小更快更简单,仅需要编写
*.proto
文件描述所需的数据结构,protobuf会实现相关类的方法。 - 提供C++、Java、Python、Go、C#等多种语言的API
安装配置
$ sudo apt-get install protobuf-compiler
定义.proto
文件
定义 proto 文件仅需给每个结构体数据定义一个 message, 然后给结构体中的每个数据添加类型和名称。
# 定义一个搜索请求的消息格式,每个请求包含查询字符串、页码、显示条数。
$ vim search.proto
message SearchRequest{
required string query = 1; //查询字符串
optional int32 page = 2; //当前页码
optional int32 pagesize = 10; //每页显示条数
}
$ vim person.proto
package tutorial;
message Person{
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType{
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message Phone{
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
required Phone phone = 4;
}
message Address{
repeated Person person = 1;
}
消息格式
消息格式有3个字符,在消息承载的数据分别对应每个字段,每个字段用有一个名字和类型。
指定字段类型
字段分为标量类型和合成类型,合成类型包括枚举(enumerations)或其他消息类型。分配标识号
在消息定义中每个字段都有唯一的标识符,用来在消息的二进制格式汇总识别各个字段,一旦开始使用就不能再更改。
最小的标识号可以从1开始,最大到2的29次方减去1即536,870,911。不可使用[19000 -19999]的标识符,protobuf协议实现中对其进行了预留。-
指定字段规则(字段修饰符)
-
required
表示值是必须设置的,格式良好的消息至少含有1个required
类型,不得超过1个。
required
是永久的,在将字段标识为required
时,应特别小心。
某些情况下若不想写入或发送一个required
的字段,将原始该字段修饰符更改为optional
可能会遇到问题,旧版本用户会认为不含该字段的消息时不完整的,从而可能会无目的的拒绝解析。在此种情况下,应考虑编写特别 针对应用的、自定义的消息校验函数。Google工程师表明,使用required
弊大于利,他们更加原意使用optional
和repeated
而不是required
,当然,它并不具有普遍性。 -
optional
消息格式中optional
选项可有0个或1个,不得超过1个。 -
repeated
在一个格式良好的消息中,repeated
字段可重复任意多次,包括0次。
重复值的顺序会被保留,表示该值可重复,相当Java中的List。
由于历史原因,基本类型的repeated
字段并没有被尽可能地高效编码,新代码中用户应该使用特殊选项[packed=true]
来保证更高效的编程。
-
repeated int 32 samples = 4 [packed = true];
- 在一个
*.proto
文件中可定义多个消息类型,定义多个相关的消息时,特别有用。
# 定义与SearchResponse消息类型对应的回复消息格式。
message SearchResponse{
required string query = 1;
optional int32 page = 2;
optional int32 pagesize = 10;
}
- 注释:
*.proto
文件注释采用C/C++/Java的//
风格。
使用注意
- 从
.proto
文件生成了什么?当用 protobuffer编译器来运行.proto
文件时,编译器将生成所选语言的代码,代码可以操作在.proto
文件中定义的消息类型、包括获取、设置字段值,将消息序列化到一个输出流中,并从 一个输入流中解析消息。 - C++,编译器为每个
*.proto
文件生成.h
和.cc
文件,.proto
文件中每个消息有一个对应的类。 - Java,编译器会为每个消息类型生成一个
.java
文件以及一个特殊的Builder类,该类时用来创建消息接口的。 - Python 编译器为
.proto
文件每个消息生成一个含有静态描述符的模块,该模块与一个元素(metaclass)在运行时(runtime)被用来创建所需的Python数据访问类。
# cocos-quick中运行项目出现错误信息
can not get file data of D:/cocos/projects/hj/src/protobuf/c.lua
[LUA-print] ----------------------------------------
[LUA-print] LUA ERROR: [string ".\app/core/protobuf/protobuf.lua"]:1: module 'pr
otobuf.c' not found:
原因:quick-cocos2dx 尚未集成google的protobuf,需在quick中添加解析protobuf的扩展。