proto文件定义了协议数据中的实体结构(message,proto文件定义了切磋数据中的实体结构(message

 

 

 

 

1.
 Protobuf简介

Protobuf的简要介绍、使用和分析

 

Protobuf的大概介绍、使用和剖析

 

 

一、protobuf是什么?

        protobuf(谷歌 Protocol
Buffers)是谷歌(Google)提供一个持有高效的商谈数据调换格式工具库(类似Json),但对照于Json,Protobuf有更高的转速功效,时间功用和空中作用都是JSON的3-5倍。后边将会有简要的demo对于那二种格式的数量转载成效的对待。但以此库如今应用还不是太流行,据说谷歌(Google)内部很多出品都有选取。

 

一、protobuf是什么?

        protobuf(谷歌(Google) Protocol
Buffers)是谷歌(Google)提供一个具备便捷的磋商数据互换格式工具库(类似Json),但对照于Json,Protobuf有更高的转载效能,时间功用和空间功能都是JSON的3-5倍。前边将会有简要的demo对于那三种格式的数目转载作用的对峙统一。但以此库近年来应用还不是太流行,据说谷歌里面很多出品都有应用。

 

     
 protobuf是google提供的一个开源体系化框架,类似于XML,JSON那样的数据表示语言,其最大的性状是基于二进制,因而比传统的XML表示急忙短小得多。固然是二进制数据格式,但并不曾就此变得复杂,开发人士通过依照一定的语法定义结构化的音讯格式,然后送给命令行工具,工具将自动生成相关的类,可以襄助php、java、c++、python等语言环境。通过将那个类富含在品种中,能够很轻松的调用相关办法来成功作业音信的连串化与反系列化工作。

二、protobuf有什么?

        Protobuf
提供了C++、java、python语言的支持,提供了windows(proto.exe)和linux平台动态编译生成proto文件对应的源文件。proto文件定义了商谈数据中的实体结构(message
,field)

关键字message: 代表了实体结构,由八个音讯字段(field)组成。

音讯字段(field): 包蕴数据类型、字段名、字段规则、字段唯一标识、默许值

数据类型:常见的原子类型都支持(在FieldDescriptor::kTypeToName中有定义)

字段规则:(在FieldDescriptor::kLabelToName中定义)

        required:必须开首化字段,尽管没有赋值,在数量连串化时会抛出相当

        optional:可选字段,可以无需开首化。

        repeated:数据可以重复(约等于java 中的Array或List)

        字段唯一标识:体系化和反系列化将会选择到。

默认值:在概念音讯字段时得以给出默许值。

 

二、protobuf有什么?

        Protobuf
提供了C++、java、python语言的辅助,提供了windows(proto.exe)和linux平台动态编译生成proto文件对应的源文件。proto文件定义了磋商数据中的实体结构(message
,field)

关键字message: 代表了实体结构,由七个新闻字段(field)组成。

音信字段(field): 包含数据类型、字段名、字段规则、字段唯一标识、默许值

数据类型:常见的原子类型都协理(在FieldDescriptor::kTypeToName中有定义)

字段规则:(在FieldDescriptor::kLabelToName中定义)

        required:必须伊始化字段,假使没有赋值,在数据种类化时会抛出极度

        optional:可选字段,可以不用发轫化。

        repeated:数据足以再度(相当于java 中的Array或List)

        字段唯一标识:种类化和反系列化将会动用到。

默认值:在概念讯息字段时能够给出默许值。

 

   
 protobuf在google中是一个相比基本的底蕴库,作为分布式运算涉及到大方的不比工作消息的传递,怎么着急速简明的表示、操作那些事情消息在google这样的宽泛使用中是任重先生而道远的。而protobuf那样的库正好是在效用、数据大小、易用性之间取得了很好的平衡。

三、protobuf有怎么着用?

       
Xml、Json是时下常用的数据调换格式,它们一贯利用字段名称保护体系化后类实例中字段与数据里面的映照关系,一般用字符串的花样保留在体系化后的字节流中。音讯和新闻的概念相对独立,可读性较好。但种类化后的多少字节很大,系列化和反种类化的岁月较长,数据传输功用不高。

       
Protobuf和Xml、Json系列化的法门各异,采纳了二进制字节的系列化方式,用字段索引和字段类型通过算法计算拿到字段之前的涉嫌映射,从而完成更高的年月功用和空中功能,尤其符合对数据大小和传输速率相比较敏感的场子使用。

三、protobuf有啥样用?

       
Xml、Json是当前常用的数据沟通格式,它们从来采纳字段名称珍爱系列化后类实例中字段与数量里面的映照关系,一般用字符串的花样保留在种类化后的字节流中。信息和音信的概念相对独立,可读性较好。但种类化后的数量字节很大,体系化和反连串化的时刻较长,数据传输功效不高。

       
Protobuf和Xml、Json种类化的措施差距,选拔了二进制字节的种类化格局,用字段索引和字段类型通过算法总计得到字段往日的涉及映射,从而达到更高的时间功用和空间作用,越发适合对数码大小和传输速率相比较灵敏的场所使用。

合法文档
http://code.google.com/p/protobuf/

四、Protobuf在Android上的选取

1、创立proto文件,定义音信的实体结构

2、编译proto文件生成对应的java文件

3、添加protobuf-java-2.5.0.jar到android工程

4、在android中贯彻对音信结构的序列化/反连串化  

 

四、Protobuf在Android上的应用

1、创立proto文件,定义音讯的实体结构

2、编译proto文件生成对应的java文件

3、添加protobuf-java-2.5.0.jar到android工程

4、在android中贯彻对音信结构的种类化/反种类化  

 

 

五、Protobuf与json的对比

五、Protobuf与json的对比

 

1、创建product.proto文件

        定义了三个Message(ProductInfo、PhoneInfo、沃特ch)新闻结构

图片 1

1、创建product.proto文件

        定义了七个Message(ProductInfo、PhoneInfo、Watch)音信结构

图片 2

2.
 Protobuf怎么样工作

2、音讯结构对应的java类(ProductInfo、PhoneInfo、沃特ch)

图片 3

 

2、音讯结构对应的java类(ProductInfo、PhoneInfo、沃特ch)

图片 4

 

 

3、音讯结构和java对象赋值

PhoneName:” idol3”

Price:2000

Top:1

 

WatchName:” tcl watch”

Price:1000

Top:1

 

3、音讯结构和java对象赋值

PhoneName:” idol3”

Price:2000

Top:1

 

WatchName:” tcl watch”

Price:1000

Top:1

 

        你首先须求在一个 .proto
文件中定义你需求做串行化的数据结构音讯。每个ProtocolBuffer信息是一小段逻辑记录,包括一体系的键值对。这里有个格外简单的
.proto 文件定义了个人音信:

4、JSON字符串

 

{“phone”:{“phoneName”:”idol3″,”price”:2000,”top”:1},”watch”:{“watchName”:”tcl
wtch”,”top”:1,”price”:1000}}

 

4、JSON字符串

 

{“phone”:{“phoneName”:”idol3″,”price”:2000,”top”:1},”watch”:{“watchName”:”tcl
wtch”,”top”:1,”price”:1000}}

 

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;

}

5、Protobuf转化后的二进制文件

图片 5

 

空中作用

Json:107个字节

Protobuf:32个字节

 

岁月效能

Json序列化: 1ms ,  反系列化:0ms

Protobuf 序列化: 0ms 反种类化:0ms

 

将public List<Phone> list和repeated PhoneInfo phoneInfoList
=3;都赋值为1000个PhoneInfo

 

空中功用

Json:4206个字节

Protobuf:1332个字节

 

日子功能

Json序列化: 4ms ,  反系列化:1ms

Protobuf 序列化: 1ms 反连串化:0ms

5、Protobuf转化后的二进制文件

图片 6

 

空中功能

Json:107个字节

Protobuf:32个字节

 

光阴功能

Json序列化: 1ms ,  反体系化:0ms

Protobuf 序列化: 0ms 反连串化:0ms

 

将public List<Phone> list和repeated PhoneInfo phoneInfoList
=3;都赋值为1000个PhoneInfo

 

空中成效

Json:4206个字节

Protobuf:1332个字节

 

岁月功能

Json序列化: 4ms ,  反连串化:1ms

Protobuf 序列化: 1ms 反系列化:0ms

如同你所见,消息格式很简短,每个音信类型拥有一个或七个特定的数字字段,每个字段拥有一个名字和一个值类型。值类型可以是数字(整数或浮点)、布尔型、字符串、原始字节或者其余ProtocolBuffer类型,还同意数据结构的分别。你可以指定可选字段,必选字段和再一次字段。你可以在(
http://code.google.com/apis/protocolbuffers/docs/proto.html
)找到更加多关于什么编写 .proto 文件的新闻。

六、protobuf的简易解析

六、protobuf的简便解析

要是你定义了祥和的报文格式(message),你就足以运作ProtocolBuffer编译器,将您的
.proto 文件编译成特定语言的类。那一个类提供了简单的措施访问每个字段(像是
query() 和 set_query()
),像是访问类的法子同样将社团串行化或反串行化。例如你能够挑选C++语言,运行编译如上的说道文件生成类叫做
Person
。随后你就足以在选用中选取那些类来串行化的读取报文音讯。你可以这么写代码:

1、优缺点

亮点:通过上述的时间功效和空中效用,可以观察protobuf的上空功能是JSON的2-5倍,时间功用要高,对于数据大小敏感,传输作用高的模块可以行使protobuf库

 

缺陷:信息结构可读性不高,种类化后的字节体系为二进制种类不可以大致的解析有效性;近年来使用不普遍,只扶助java,C++和Python;

 

1、优缺点

亮点:通过以上的日子功效和空间作用,可以观望protobuf的上空效用是JSON的2-5倍,时间成效要高,对于数据大小敏感,传输作用高的模块可以运用protobuf库

 

缺点:信息结构可读性不高,种类化后的字节系列为二进制体系不可以大致的辨析有效性;如今使用不广泛,只帮助java,C++和Python;

 

Person person;

person.set_name("John Doe");

person.set_id(1234);

person.set_email("jdoe@example.com");

fstream.output("myfile",ios::out | ios::binary);

person.SerializeToOstream(&output);

2、数据体系化/反系列化

2、数据系列化/反体系化

下一场,你能够读取报文中的数据:

a、规则:

protobuf把音讯结果message也是经过
key-value对来表示。只是其中的key是应用一定的算法统计出来的即因此各样message中各类字段(field
index)和字段的数据类型举行演算得来的key = (index<<3)|type;

type类型的呼应关系如下:

 

Type

Meaning

Used For

0

Varint

int32, int64, uint32, uint64, sint32, sint64, bool, enum

1

64-bit

fixed64, sfixed64, double

2

Length-delimited

string, bytes, embedded messages, packed repeated fields

3

Start group

groups (deprecated)

4

End group

groups (deprecated)

5

32-bit

fixed32, sfixed32, float

 

Value会依据数据类型的分化会有三种表现形式:

对于各个int,bool,enum类型,value就是Varint

对此string,bytes,message等等类型,value就是length+原始内容编码

 

Varints是一种紧凑表示数字的法子。它用一个要么七个字节表示一个数字,值越小的数字字节数越少。绝对于传统的用4字节代表int32门类数字,Varints对于小于128的数值都足以用一个字节表示,大于128的数值会用越来越多的字节来代表,对于很大的多少则需求用5个字节来表示。

 

Varints算法描述:
每一个字节的最高位都是有特异意义的,若是是1,则意味继续的字节也是该数字的一有些;假如是0,则甘休

a、规则:

protobuf把音讯结果message也是透过
key-value对来表示。只是其中的key是采纳一定的算法统计出来的即通过各样message中各样字段(field
index)和字段的数据类型举办演算得来的key = (index<<3)|type;

type类型的附和关系如下:

 

Type

Meaning

Used For

0

Varint

int32, int64, uint32, uint64, sint32, sint64, bool, enum

1

64-bit

fixed64, sfixed64, double

2

Length-delimited

string, bytes, embedded messages, packed repeated fields

3

Start group

groups (deprecated)

4

End group

groups (deprecated)

5

32-bit

fixed32, sfixed32, float

 

Value会根据数据类型的两样会有三种表现情势:

对此各类int,bool,enum类型,value就是Varint

对于string,bytes,message等等类型,value就是length+原始内容编码

 

Varints是一种紧凑表示数字的不二法门。它用一个依然多个字节表示一个数字,值越小的数字字节数越少。相对于传统的用4字节表示int32品种数字,Varints对于小于128的数值都足以用一个字节表示,大于128的数值会用越来越多的字节来表示,对于很大的多少则须求用5个字节来表示。

 

Varints算法描述:
每一个字节的万丈位都是有更加含义的,即便是1,则表示继续的字节也是该数字的一有的;即使是0,则甘休

fstream input("myfile",ios::in | ios:binary);

Person person;

person.ParseFromIstream(&input);

cout << "Name: " << person.name() << endl;

cout << "E-mail: " << person.email() << endl;

b、demo生成的的二进制文件反种类化。

第1个字节 (0A)

字段索引(index):         0A = 0001010  0A>>3 = 001 = 1

数据类型(type):           0A = 0001010&111  = 2 (String);

 

第2个字节 (0C)

字符串长度(length):      0E = 12;

字符串:                         0A 05 69 64 6F 6C 33 10 01 18 BD 0F

 

第3个字节 (0A)

因为字符串是源于phoneInfo属于嵌套类型

字段索引(index):         0A = 0001010  0A>>3 = 001 = 1

数据类型(type):           0A = 0001010&111  = 2 (String);

第4-9个字节(69 64 6F 6C 33)

字符串长度(length):    05 = 5

字符串:                       69 64 6F 6C 33 = idol3

 

第10个字节 (10)

字段索引(index):         10 = 00010000    10A>>3 = 0010 = 2

数据类型(type):           10 = 00010000&111  = 0 (Varints);

 

第11个字节  (01)

Varints:                          01 = 00001字节的参天位为0 整数为止

Value:                            1;

 

第12个字节(18)

字段索引(index):           18 = 00011000    18>> 00011 = 3

数据类型(type):           18 = 00011000&111  = 0 (Varints);

 

第13个字节(D0)

高高的位为1,整数计算到下一个字节

 

第14个字节(0F)

参天位为0,整数总计截至

Value:为11111010000 =2000

 

b、demo生成的的二进制文件反系列化。

第1个字节 (0A)

字段索引(index):         0A = 0001010  0A>>3 = 001 = 1

数据类型(type):           0A = 0001010&111  = 2 (String);

 

第2个字节 (0C)

字符串长度(length):      0E = 12;

字符串:                         0A 05 69 64 6F 6C 33 10 01 18 BD 0F

 

第3个字节 (0A)

因为字符串是根源phoneInfo属于嵌套类型

字段索引(index):         0A = 0001010  0A>>3 = 001 = 1

数据类型(type):           0A = 0001010&111  = 2 (String);

第4-9个字节(69 64 6F 6C 33)

字符串长度(length):    05 = 5

字符串:                       69 64 6F 6C 33 = idol3

 

第10个字节 (10)

字段索引(index):         10 = 00010000    10A>>3 = 0010 = 2

数据类型(type):           10 = 00010000&111  = 0 (Varints);

 

第11个字节  (01)

Varints:                          01 = 00001字节的万丈位为0 整数停止

Value:                            1;

 

第12个字节(18)

字段索引(index):           18 = 00011000    18>> 00011 = 3

数据类型(type):           18 = 00011000&111  = 0 (Varints);

 

第13个字节(D0)

最高位为1,整数统计到下一个字节

 

第14个字节(0F)

摩天位为0,整数统计停止

Value:为11111010000 =2000

 

你可以在不影响向后万分的情状下肆意给数据结构增添字段,旧有的数据会忽略新的字段。所以一旦利用ProtocolBuffer作为通讯协议,你可以不要担心破坏现有代码的动静下伸张协议。

C、反连串化结果

phoneinfo为

phoneName = “idol3”

top = 1

price = 2000;

 

如出一辙的不二法门watchInfo为:

watchName = “tcl name”

top = 1

price=2000 

C、反体系化结果

phoneinfo为

phoneName = “idol3”

top = 1

price = 2000;

 

同样的法子watchInfo为:

watchName = “tcl name”

top = 1

price=2000 

你可以在API参考(
http://code.google.com/apis/protocolbuffers/docs/reference/overview.html
)中找到完整的参阅,而有关ProtocolBuffer的报文格式编码则可以在(
http://code.google.com/apis/protocolbuffers/docs/encoding.html )中找到。

3、时间功用

经过protobuf种类化/反系列化的经过可以汲取:protobuf是透过算法生成二进制流,连串化与反体系化不必要分析相应的节点属性和剩余的叙述音信,所以系列化和反系列化时间作用较高。

3、时间功效

经过protobuf体系化/反种类化的进度可以得出:protobuf是因此算法生成二进制流,种类化与反体系化不必要分析相应的节点属性和剩下的叙说音信,所以序列化和反连串化时间作用较高。

 

4、空间效能

xml、json是用字段名称来确定类实例中字段之间的独立性,所以体系化后的多寡多了很多叙述音讯,增添了种类化后的字节系列的容量。

 

Protobuf的种类化/反体系化进度可以得出:

protobuf是由字段索引(fieldIndex)与数据类型(type)统计(fieldIndex<<3|type)得出的key维护字段之间的照耀且只占一个字节,所以相比较json与xml文件,protobuf的系列化字节没有过多的key与叙述符新闻,所以占用空间要小很多。

4、空间效用

xml、json是用字段名称来规定类实例中字段之间的独立性,所以系列化后的多少多了好多讲述音讯,扩张了体系化后的字节序列的容量。

 

Protobuf的种类化/反系列化进度可以汲取:

protobuf是由字段索引(fieldIndex)与数据类型(type)计算(fieldIndex<<3|type)得出的key维护字段之间的炫耀且只占一个字节,所以相比较json与xml文件,protobuf的种类化字节没有过多的key与讲述符音信,所以占用空间要小很多。

 

七、Protobuf的源码分析

七、Protobuf的源码分析

3.
 Protobuf消息定义

1、protobuf在java使用的系列化流程

 

java程序调用parserFrom(byte[]
data)开首字节系列的反种类,Java程序通过调用编译生类GenerateMessage中的wirteTo()方法开头将系列化后的字节写入输出流中

 图片 7

图片 8

GenerateMessage
继承AbstractMessage类,种类化最后在AbstractMesssage中落成,连串化的贯彻进度:

a、遍历对象中Message结构()

调用AbstractMessage类中的writeTo()方法

 图片 9

b、 系列化Message中每一个字段

调用CodeOutputStream类中的writeMessageSetExtension()方法

图片 10

 

c、 对于Varints  Tag 的体系化流程:

调用CodeOutputStream类中的writeUInt32()方法

图片 11

调用CodeOutputStream类中的WriteRawVarint32()方法

图片 12

 

d、 对于非Varints Tag的序列化

调用CodeOutputStream类中的WriteTag()方法

图片 13 

图片 14

 

现实的系列化落成都在CodedOutputStream中做到

 

1、protobuf在java使用的体系化流程

 

java程序调用parserFrom(byte[]
data)伊始字节系列的反体系,Java程序通过调用编译生类GenerateMessage中的wirteTo()方法先导将系列化后的字节写入输出流中

 图片 15

图片 16

GenerateMessage
继承AbstractMessage类,种类化最后在AbstractMesssage中形成,系列化的兑现进程:

a、遍历对象中Message结构()

调用AbstractMessage类中的writeTo()方法

 图片 17

b、 系列化Message中每一个字段

调用CodeOutputStream类中的writeMessageSetExtension()方法

图片 18

 

c、 对于Varints  Tag 的系列化流程:

调用CodeOutputStream类中的writeUInt32()方法

图片 19

调用CodeOutputStream类中的WriteRawVarint32()方法

图片 20

 

d、 对于非Varints Tag的系列化

调用CodeOutputStream类中的WriteTag()方法

图片 21 

图片 22

 

切切实实的连串化完成都在CodedOutputStream中形成

 

 

2、java使用protobuf 的反体系化流程分析

java程序通过调用parserFrom(byte[] data)开首反连串化

 图片 23

图片 24

切实在com.google.protobuf. AbstractParser类中落到实处

 

图片 25

 

图片 26

图片 27

 

图片 28

 

 

末段在com.google.protobuf.CodedInputStream类中落成反系列化

2、java使用protobuf 的反序列化流程分析

java程序通过调用parserFrom(byte[] data)起先反连串化

 图片 29

图片 30

现实在com.google.protobuf. AbstractParser类中完结

 

图片 31

 

图片 32

图片 33

 

图片 34

 

 

最终在com.google.protobuf.CodedInputStream类中做到反体系化

 

3、动态编译

以windows下用protoc.exe工具已毕proto文件编译为例,protoc.exe是用C++落成。在控制台执行命令:

图片 35

编译的流水线:

反省proto的语法规则

将proto的文书中的message结构转换为GenerateMessage类的子类,并落到实处Builder接口。

编译流程

Main.cc中的main()方法

图片 36

 

Command_line_interface.cc中的Run()方法

图片 37

 

Import类中Import()

图片 38

 

在Descriptor中落成message信息的搜集和转化。

3、动态编译

以windows下用protoc.exe工具达成proto文件编译为例,protoc.exe是用C++完结。在控制台执行命令:

图片 39

编译的流水线:

反省proto的语法规则

将proto的文件中的message结构转换为GenerateMessage类的子类,并贯彻Builder接口。

编译流程

Main.cc中的main()方法

图片 40

 

Command_line_interface.cc中的Run()方法

图片 41

 

Import类中Import()

图片 42

 

在Descriptor中形成message新闻的募集和转载。

     
要通讯,必须有商榷,否则两者无法清楚对方的码流。在protobuf中,协议是由一文山会海的音信构成的。因而最爱慕的就是概念通讯时利用到的消息格式。

 

信息由至少一个字段组合而成,类似于C语言中的结构。每个字段都有自然的格式。

字段格式:限定修饰符① | 数据类型② | 字段名称③ | = | 字段编码值④ |
[字段默许值⑤]

①.限定修饰符包括 required\optional\repeated

 

Required:
表示是一个亟须字段,必须相对于发送方,在发送新闻从前务必设置该字段的值,对于接收方,必须可以分辨该字段的意趣。发送之前从未安装required字段或者不能识别required字段都会引发编解码十分,导致新闻被撇下。

Optional:表示是一个可选字段,可选对于发送方,在殡葬音讯时,可以有选取性的安装或者不设置该字段的值。对于接收方,如若可以分辨可选字段就展开对应的处理,如若无法辨别,则忽略该字段,信息中的其它字段正常处理。—因为optional字段的特征,很多接口在提升版本中都把新生增进的字段都合并的装置为optional字段,那样老的本子无需升级程序也能够正常的与新的软件进行通讯,只可是新的字段不能分辨而已,因为并不是种种节点都须要新的意义,由此得以成功按需提高和平滑过渡。

Repeated:表示该字段能够包罗0~N个元素。其性状和optional一样,可是每一趟可以包括三个值。可以用作是在传递一个数组的值。

 

②.数据类型

 

Protobuf定义了一套基本数据类型。差不离都足以映射到C++\Java等语言的功底数据类型.

      

protobuf 数据类型

描述

打包

C++语言映射

bool

布尔类型

1字节

bool

double

64位浮点数

N

double

float

32为浮点数

N

float

int32

32位整数、

N

int

uin32

无符号32位整数

N

unsigned int

int64

64位整数

N

__int64

uint64

64为无符号整

N

unsigned __int64

sint32

32位整数,处理负数效率更高

N

int32

sing64

64位整数 处理负数效率更高

N

__int64

fixed32

32位无符号整数

4

unsigned int32

fixed64

64位无符号整数

8

unsigned __int64

sfixed32

32位整数、能以更高的效率处理负数

4

unsigned int32

sfixed64

64为整数

8

unsigned __int64

string

只能处理 ASCII字符

N

std::string

bytes

用于处理多字节的语言字符、如中文

N

std::string

enum

可以包含一个用户自定义的枚举类型uint32

N(uint32)

enum

message

可以包含一个用户自定义的消息类型

N

object of class

N 代表打包的字节并不是永恒。而是基于数量的深浅或者长度。

譬如int32,即便数值相比小,在0~127时,使用一个字节打包。

有关枚举的打包格局和uint32如出一辙。

关于message,类似于C语言中的结构包蕴别的一个结构作为数据成员平等。

关于 fixed32
和int32的分别。fixed32的打包功能比int32的功效高,但是选拔的半空中一般比int32多。因而一个属于时间功用高,一个属于空间功能高。依照项目标实际情状,一般选拔fixed32,借使赶上对传输数据量须要比较苛刻的环境,可以采取int32.

③.字段名称

 

字段名称的命名与C、C++、Java等语言的变量命有名的模特式大概是均等的。

protobuf提出字段的命名接纳以下划线分割的驼峰式。例如 first_name
而不是firstName.

④.字段编码值

有了该值,通讯双方才能互相识别对方的字段。当然相同的编码值,其范围修饰符和数据类型必须一致。

编码值的取值范围为 1~2^32(4294967296)。

其中
1~15的编码时间和空中功能都是参天的,编码值越大,其编码的年华和空间作用就越低(相对于1-15),当然一般景况下邻座的2个值编码功用的是一致的,除非2个值恰好实际4字节,12字节,20字节等的临界区。比如15和16.

1900~2000编码值为谷歌(Google) protobuf
系统内部保留值,提出并非在团结的品类中选择。

protobuf 还提议把平常要传递的值把其字段编码设置为1-15里边的值。

音讯中的字段的编码值无需屡次三番,只假诺合法的,并且不可以在同一个新闻中有字段包括相同的编码值。

提出:项目投入运营之后涉及到版本升级时的新增音信字段全体拔取optional或者repeated,尽量不实用required。若是利用了required,需要全网统一升级,借使选择optional或者repeated能够平滑升级。

 

⑤.默许值。当在传递数据时,对于required数据类型,即使用户没有安装值,则动用默许值传递到对端。当接受多少是,对于optional字段,借使没有接过到optional字段,则设置为默许值。

 

关于import

protobuf 接口文件可以像C语言的h文件一个,分离为多少个,在急需的时候经过
import导入须要对文件。其一坐一起和C语言的#include或者java的import的作为大约相同。

关于package

幸免名称争持,可以给各类文件指定一个package名称,对于java解析为java中的包。对于C++则分析为名称空间。

 

关于message

协助嵌套消息,新闻可以蕴含另一个音信作为其字段。也得以在音信内定义一个新的音信。

关于enum

枚举的概念和C++相同,不过有部分范围。

枚举值必须大于等于0的整数。

使用分号(;)分隔枚举变量而不是C++语言中的逗号(,)

eg.

enum VoipProtocol 

{

    H323 = 1;

    SIP  = 2;

    MGCP = 3;

    H248 = 4;

}

 

4.
 Protobuf的PHP实例

以下,为了深切了然protobuf。我们运用php示例:

php protobuf 下载地址http://code.google.com/p/pb4php/downloads/list

C#
protobuf
下载地址http://code.google.com/p/protobuf/downloads/list
protobuf语言使用
http://www.cnblogs.com/dkblog/archive/2012/03/27/2419010.html

php使用protobuf,然后再测试通信。

下载的example的pb_proto_test_new.php是由难点的。

1、 下载:php protobuf 

下载地址http://code.google.com/p/pb4php/downloads/list

http://pb4php.googlecode.com/files/protocolbuf\_025.zip

将下载好的proto扩充库,解压到wwwroot目录下

 

2、先写一个proto文件

我们使用库里面提供的proto文件:test_new.proto。那个文件是在example。大家把它移到新建的文件mytest目录下。

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];
 
}
 
// a simple comment
 
repeated PhoneNumber phone = 4;
 
optional string surname = 5;
}

message
AddressBook {
 
repeated Person person = 1;
}

message
Test {
 
repeated string person = 2;
}

 

3、生成pb_proto_test_new.php文件

实在该文件已经存在example目录下啦。

但有原始生成的那一个文件有难题。根本没有那几个常量:var $wired_type =
PBMessage::WIRED_STRING;

 

php不援救proto里的package,所以php版编译此前先要删掉package语句。然后在mytest目录建立一个create_test_new.php文件存放编译命令:

<?php
require_once(‘../parser/pb_parser.php’);
$parser = new PBParser();
$parser->parse(‘./test_new.proto’);
echo ‘ok;

结果在mytest目录下生成一个文本:pb_proto_test_new.php

 

到此,假诺那些数目协议是在客户端。那么我们客户端也使用php代码:大家一向利用代码库example里面的演示:

 

4、运行实例:

即运行test_new.php:

<?php
// first include pb_message
require_once(‘../message/pb_message.php’);

// include the generated file
require_once(‘./pb_proto_test_new.php’);

// generate message with the new definition with surname
// now just test the classes
$book = new AddressBook();
$person = $book->add_person();
$person->set_name(‘Nikolai’);
$person = $book->add_person();
$person->set_name(‘Kordulla’);
$person->set_surname(‘MySurname’);

$phone_number = $person->add_phone();
$phone_number->set_number(‘0711’);
$phone_number->set_type(Person_PhoneType::WORK);

$phone_number = $person->add_phone();
$phone_number->set_number(‘0171’);
$phone_number->set_type(Person_PhoneType::MOBILE);

$phone_number = $person->add_phone();
$phone_number->set_number(‘030’);

// serialize
$string = $book->SerializeToString();

// write it to disk
file_put_contents(‘test.pb’, $string);

?>

test.pb是生成的二进制文件
基本结构一个字节类型+ 字节长度

从上述操作和类库源代码来看打包速度可能慢很多。
空间节省倒是卓殊好。符合 protobuf
定义:作用、数据大小、易用性之间的平衡。

 

5、服务器读取协议内容.

如若test.pb文件是因此网络传输到服务器上的(那里都是在本土)。

然后服务器端也足以按照那一个协议,生成对应类。例如example下边的test.proto:

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];
  }
  // a simple comment
  repeated PhoneNumber phone = 4;
}

message AddressBook {
  repeated Person person = 1;
}

 

运行test.php:

<?php
// EXECUTE test_new.php first 

// first include pb_message
require_once(‘../message/pb_message.php’);

// now read it with the old file
// include the generated file
require_once(‘./pb_proto_test.php’);

$string = file_get_contents(‘./test.pb’);

// Just read it
$book = new AddressBook();
$book->parseFromString($string);

var_dump($book->person_size());
$person = $book->person(0);
var_dump($person->name());
$person = $book->person(1);
var_dump($person->name());
var_dump($person->phone(0)->number());
var_dump($person->phone(0)->type());
var_dump($person->phone(1)->number());
var_dump($person->phone(1)->type());
var_dump($person->phone(2)->number());
var_dump($person->phone(2)->type());
?>

读取出客户端相应的内容。

 

 

 

5.
 Protobuf与Thrift

 

数据类型

protobuf thrift protobuf thrift protobuf thrift protobuf thrift

double

double

float

 

 

byte

 

i16

int32

i32

int64

i64

uint32

 

uint64

 

sint32

 

sint64

 

fixed32

 

fixed64

 

sfixed32

 

sfixed64

 

bool

bool

string

string

bytes

binary

message

struct

enum

enum

service

service

综合相比较

  protobuf thrift
功能特性 主要是一种序列化机制 提供了全套RPC解决方案,包括序列化机制、传输层、并发处理框架等
支持语言 C++/Java/Python C++, Java, Python, Ruby, Perl, PHP, C#, Erlang, Haskell
易用性 语法类似,使用方式等类似
生成代码的质量 可读性都还过得去,执行效率另测
升级时版本兼容性 均支持向后兼容和向前兼容
学习成本 功能单一,容易学习 功能丰富、学习成本高
文档&社区 官方文档较为丰富,google搜索protocol buffer有2000W+结果,google group被墙不能访问 官方文档较少,没有API文档,google搜索apache thrift仅40W结果,邮件列表不怎么活跃

属性比较
鉴于thrift功用较protobuf丰裕,因而单从序列化机制上展开质量相比,依据种类化后字节数、种类化时间、反种类化时间多个目的举办,对thrift的二进制、压缩、protobuf两种格式举行自查自纠。

测试方法:取了15000+条样本数量,分别写了多个目标的测试程序,在本人自己的微机上实施,其中时间测试循环1000次,总的种类化/反连串化次数1500W+。

平均字节数

thrift二进制 535
thrift压缩 473
protobuf 477

序列化(1500W次)时间(ms)

thrift二进制 306034
thrift压缩 304256
protobuf 177652

反体系化(1500W次)时间(ms)

thrift二进制 287972
thrift压缩 315991
protobuf 157192

thrift的时间测试可能不是很准,由于thrift发生代码的纷纭,编写的测试代码为了适应其接口,在调用堆栈上可能有一对额外费用。

 

 

http://blog.csdn.net/new\_abc/article/details/48105903

相关文章