公海赌船网址proto文件定义了商讨数遭到的实业结构(messageproto文件定义了协和数中之实业结构(message如何高效简明的象征、操作这些业务信息在google这样的常见利用中凡是第一的。

 

 

 

 

Protobuf的略介绍、使用和分析

 

Protobuf的简约介绍、使用及分析

 

  1.  Protobuf简介

一、protobuf是什么?

        protobuf(Google Protocol
Buffers)是Google提供一个有快速的磋商数据交换格式工具库(类似Json),但比于Json,Protobuf有双重强之转折效率,时间效率与空间效率还是JSON的3-5倍增。后面将会见时有发生简要的demo对于这片种格式的数转发效率的对照。但此库房时用还非是极度盛,据说谷歌内部多出品还有下。

 

一、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中实现对信息结构的序列化/反序列化  

 

2.
 Protobuf如何工作

五、Protobuf与json的对比

五、Protobuf与json的对比

        你首先用以一个 .proto
文件被定义你待开串行化的数据结构信息。每个ProtocolBuffer信息是如出一辙略段逻辑记录,包含一多样的键值对。这里有个非常简单的
.proto 文件定义了个人信息:

1、创建product.proto文件

        定义了三个Message(ProductInfo、PhoneInfo、Watch)消息结构

公海赌船网址 1

1、创建product.proto文件

        定义了三独Message(ProductInfo、PhoneInfo、Watch)消息结构

公海赌船网址 2

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;
}

2、消息结构对应之java类(ProductInfo、PhoneInfo、Watch)

公海赌船网址 3

 

2、消息结构对应之java类(ProductInfo、PhoneInfo、Watch)

公海赌船网址 4

 

似你所显现,消息格式很简单,每个消息类型有一个要多个特定的数字字段,每个字段拥有一个名与一个值类型。值类型可以是数字(整数或浮点)、布尔型、字符串、原始字节或者其他ProtocolBuffer类型,还同意数据结构的个别。你可以指定可选字段,必选字段与重新字段。你可以当(
http://code.google.com/apis/protocolbuffers/docs/proto.html
)找到更多关于怎样编写 .proto 文件之音讯。

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

 

一经您定义了投机的报文格式(message),你就是足以运作ProtocolBuffer编译器,将您的
.proto 文件编译成特定语言的切近。这些类似提供了简便的措施访问每个字段(像是
query() 和 set_query()
),像是访问类的办法同样以组织串行化或反串行化。例如你得择C++语言,运行编译如齐的合计文件生成类叫做
Person
。随后而不怕得当采用被使是看似来串行化的读取报文信息。你可如此形容代码:

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}}

 

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);

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

下一场,你可以读取报文中的数额:

六、protobuf的简要分析

六、protobuf的概括解析

fstream input("myfile",ios::in | ios:binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;

1、优缺点

亮点:通过以上的日效率以及空间效率,可以望protobuf的长空效率是JSON的2-5倍,时间效率要高,对于数据大小敏感,传输效率高之模块可行使protobuf库

 

症结:消息结构可读性不强,序列化后的配节序列为二进制序列不可知大概的分析中;目前采用非普遍,只支持java,C++和Python;

 

1、优缺点

亮点:通过上述之时间效率及空中效率,可以视protobuf的上空效率是JSON的2-5倍增,时间效率要大,对于数据大小敏感,传输效率高的模块可使用protobuf库

 

短:消息结构可读性不赛,序列化后的配节序列为二进制序列不能够简单的剖析中;目前采取未广泛,只支持java,C++和Python;

 

乃可在无影响朝后相当的事态下肆意给数据结构增加字段,旧片数据会忽略新的字段。所以一旦利用ProtocolBuffer作为通信协议,你可以不要担心破坏现有代码的动静下扩展协议。

2、数据序列化/反序列化

2、数据序列化/反序列化

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

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,则结束

3.
 Protobuf消息定义

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

 

 
   
要通信,必须产生协议,否则两者无法掌握对方的码流。在protobuf中,协议是由于同文山会海之音讯构成的。因此最好要的就是概念通信时使用到的音格式。

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 

信息由至少一个字段组合而成,类似于C语言中的构造。每个字段都产生肯定的格式。

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与讲述称信息,所以占用空间要多少多。

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

七、Protobuf的源码分析

七、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中成功

 

Required:
表示是一个必字段,必须相对于发送方,在发送信息之前须装该字段的价值,对于接收方,必须能够分辨该字段的意。发送之前没安装required字段或者无法识别required字段都见面引发编解码异常,导致信息被废。

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类中成就反序列化

Optional:表示是一个可是卜字段,可挑选对发送方,在发送信息不时,可以生选择性的安或未装该字段的价值。对于接收方,如果能辨识而选取字段就是展开对应的处理,如果无法辨认,则忽略该字段,消息受到的其他字段正常处理。—因为optional字段的特性,很多接口在提升版本中都管新生添加的字段都统一之安装为optional字段,这样一直的本子无需提升程序也足以健康的跟新的软件进行通信,只不过新的字段无法辨识而已,因为并无是每个节点都亟待新的意义,因此得以成功以需要提升和平滑过渡。

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消息的采集及转发。

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产生代码的复杂性,编写的测试代码为了适应其接口,在调用堆栈上或者有一部分额外开销。

相关文章