Protobuf简介

1. 用途:

 把某种数据结构的信息,以某种格式保存起来。主要用于数据存储、传输协议格式等场合。

2. 优点:

  a.性能好,效率高(时间和空间上比XML好,XML反序列化开销大)

  b.代码生成机制

eg:

    假设订单包括如下属性:

--------------------------------

    时间:time(用整数表示)

    客户id:userid(用整数表示)

    交易金额:price(用浮点数表示)

    交易的描述:desc(用字符串表示)

--------------------------------

    如果使用protobuf实现,首先要写一个proto文件(不妨叫Order.proto),在该文件中添加一个名为"Order"的message结构,用来描述通讯协议中的结构化数据。该文件的内容大致如下:

 

--------------------------------

message Order

{

  required int32 time = 1;

  required int32 userid = 2;

  required float price = 3;

  optional string desc = 4;

}

--------------------------------

 

 

    然后,使用protobuf内置的编译器编译 该proto。由于本例子的模块是C++,你可以通过protobuf编译器的命令行参数(看“这里 ”),让它生成C++语言的“订单包装类”。(一般来说,一个message结构会生成一个包装类)

    然后你使用类似下面的代码来序列化/解析该订单包装类:

 

--------------------------------

// 发送方

Order order;

order.set_time(XXXX);

order.set_userid(123);

order.set_price(100.0f);

order.set_desc("a test order");

string sOrder;

order.SerailzeToString(&sOrder);

// 然后调用某种socket的通讯库把序列化之后的字符串发送出去

// ......

--------------------------------

// 接收方

string sOrder;

// 先通过网络通讯库接收到数据,存放到某字符串sOrder

// ......

Order order;

if(order.ParseFromString(sOrder))  // 解析该字符串

{

  cout << "userid:" << order.userid() << endl

          << "desc:" << order.desc() << endl;

}

else

{

  cerr << "parse error!" << endl;

}

 

--------------------------------

 

    有了这种代码生成机制,开发人员就不用再编写协议解析的代码。万一将来需求发生变更,要求给订单再增加一个“状态”的属性,那只需要在Order.proto文件中增加一行代码。对于发送方(模块A),只要增加一行设置状态的代码;对于接收方(模块B)只要增加一行读取状态的代码。

  c.支持“向后兼容”和“向前兼容”

     “向后兼容”:当模块B升级之后,它能够正确识别模块A发出的老版本的协议。如上例中,由于老版本没有“状态”这个属性,在扩充协议时,可以考虑把“状态”属性设置成为非必填的,或者给“状态”属性设置一个缺省值。

    “向前兼容”:当模块A升级以后,模块B能够 正常识别模块A发出的新版本的协议,这时新增加的“状态”属性会被忽略。

  d.支持多种编程语言(官方源代码中包含了C++、Java、Python三种语言)

3. 缺点:

  a.应用不够广

  b.二进制格式导致可读性差

  c.缺乏自描述

posted @ 2013-11-20 16:59  猫猫去流浪  阅读(300)  评论(2编辑  收藏  举报