protobuf

参考链接:
https://blog.csdn.net/caisini_vc/article/details/5599468
https://www.cnblogs.com/chenyangyao/p/5422044.html
https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message

安装过程:

$ git clone https://github.com/protocolbuffers/protobuf.git
$ cd protobuf
$ git submodule update --init --recursive
$ ./autogen.sh
$ ./configure
$ make
$ make check
$ sudo make install
$ sudo ldconfig

一.背景介绍

  • protobuf用来做什么的
    protobuf是谷歌开源的一个项目,是用来保存格式化的一些数据,或者用来定义网络通信的数据格式,全名叫protocol buffers.

  • protobuf有什么特色
    1.性能好,效率高,传输二进制格式的数据
    2.代码生成机制优良,自动产生序列化和反序列化的代码避免我们程序员手动的解析
    3.支持多种语言
    4.插入新的字段十分方便,在对应的message中添加新的一行字段即可,解析的时候我们只需要解析需要的字段即可.

二.简单实例

需要注意的是,如果我们需要使用
假如我这里有一个商务系统,我需要在客户端和服务器端使用socket来回的传输一个订单的信息,这样一个交互的过程,这里描述的是用protobuf来作为通信双方数据传输的格式:

订单的基本信息:
时间:time         int 
客户:id           int 
交易金额: price    float
交易的描述:desc    string

用protobuf作为传输协议,需要定义以proto结尾的文件,这里起名为order.proto
最后需要在该文件中定义message结构,用来描述socket通信中数据的格式

//message用来指定我们想要序列化的数据结构
message order
{
  required int32 time = 1;
  required int32 userid = 2;
  required float price = 3;
  optional string desc = 4;
}
//每一个message类型的结构都含有一个或者多个字段,每个字段对应唯一的编号

数据格式定义好了,接下来就是"发送方"进行数据的初始化和发送
"接收方"进行数据的接收和解析,如下:

//发送端

/*
指定版本 以及 引入一些包 如
syntax = "proto2";
package google.protobuf;
*/

order order;  //定义数据格式后,进行初始化
order.set_time(XXXX);
order.set_userid(123);
order.set_price(100.0f);
order.set_desc("a test order");

/*
一旦我们定义好了message,我们就可以使用如c++编译器来编译.proto文件
生成数据的访问类,这种类为每一个字段提供了简单的访问器,如set_name()等方法
当然也提供了反序列化的函数,用于接收方将string类型的数据回写到message中,或者将数据读到别的地方

*/


string str;
order.SerailzeToString(&str);
//定义string类型,将protobuf中数据格式转换成string类型并存放到str中
/*
	通过socket讲字符串发送出去
*/

//接收端

string str;  //定义string类型字符串用来存放发送端发送的数据
/*
	通过socket将字符串接收
*/
order or;//定义相应数据类型的数据格式

if(or.ParseFromString(str))  // 解析该字符串,并写会到proto数据格式中
{
  cout << "userid:" << or.userid() << endl
          << "desc:" << or.desc() << endl;
}
else
{
  cerr << "parse error!" << endl;
}

三.protobuf的缺点

  1. 应用不够广,虽然性能较好,但是知名度不够高,可能一些三方库的支持上没那么好;
  2. 二进制传输不容易读;

四.编译与应用

编译:
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/order.proto

SRC_DIR 表示proto文件所在的目录,cpp_out指定了生成的代码的路径,
$SRC_DIR/order.proto指proto文件

如果是当前的目录下的话:
protoc -I=./ --cpp_out=./ protocol.proto
在当前目录生成了protocol.pb.cc和protocol.pb.h两个文件。

应用:
把生成了protocol.pb.cc和protocol.pb.h加入到工程,那么接着就是调用一些API,完成序列化和反序列化

对于新手建议学习proto3版本.

字段修饰符
proto2:

required:必须的
optional:可选的
repeated:重复的(类比数组,可以为0)

proto3:

singular:单一的(默认,可以省略)
repeated:重复的

五.序列化和非序列化

序列化:
SerializedAsString(),SerializedToString(std::string*):序列化为std::string
SerializedToArray(void*,int):序列化为byte数组
SerializedToOstream(ostream*):序列化到输出流

反序列化:
ParseFromString(std::string& data):从字符串中反序列化
ParseFromArray(const void *,int):从字节序中反序列化
ParseFromIstream(istream*):从输入流中反序列化

六.proto2与proto3的区别

  1. 在第一行非空白非注释行,必须写: syntax = “proto3”;
    字段规则移除了 “required”,并把 “optional” 改名为 “singular”1;
  2. 枚举类型的第一个字段必须为 0 ;这也是一个约定
  3. 移除了 default 选项;
    在 proto2 中,可以使用 default 选项为某一字段指定默认值。在 proto3 中,字段的默认值只能根据字段类型由系统决定。也就是说,默认值全部是约定好的,而不再提供指定默认值的语法。
    在字段被设置为默认值的时候,该字段不会被序列化。这样可以节省空间,提高效率。
    但这样就无法区分某字段是根本没赋值,还是赋值了默认值。这在 proto3 中问题不大,但在 proto2 中会有问题。
    比如,在更新协议的时候使用 default 选项为某个字段指定了一个与原来不同的默认值,旧代码获取到的该字段的值会与新代码不一样。
  4. 移除了对分组的支持;
    分组的功能完全可以用消息嵌套的方式来实现,并且更清晰。在 proto2 中已经把分组语法标注为『过期』了.
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值