> 文章列表 > protobuf序列化原理、安装与应用

protobuf序列化原理、安装与应用

protobuf序列化原理、安装与应用

目录

protobuf序列化

 protobuf的原理

 protobuf 的安装

编译message文件

应用protobuf


protobuf序列化

        protobuf是一种比json和xml等序列化工具更加轻量和高效的结构化数据存储格式,性能比json和xml真的强很多,毕竟google出品。

        官网:https://developers.google.com/protocol-buffers/

 protobuf的原理

 protobuf 的安装

apt-get install autoconf automake libtool curl make g++ unzip
$ git clone https://github.com/google/protobuf.git 
$ cd protobuf 
$ git submodule update --init --recursive 
$ ./autogen.sh 
$ ./configure 
$ make 
$ make check 
$ sudo make install 
$ sudo ldconfig 

定义message

所有的message必须定义到一个文件中,且文件的后缀名为.proto。例如我们定义的bike.proto文件

syntax = "proto2";package tutorial;message mobile_request
{required string mobile = 1;
}message mobile_response
{required int32 code   = 1;   //响应代号required int32 icode  = 2;   //验证码optional string data  = 3;   //失败原因
}message login_request
{required string mobile  = 1;    // 手机号码required int32  icode   = 2;    // 验证码
}message login_response
{required int32   code   = 1;    // 响应代号optional string  desc   = 2;    // 验证码
}message recharge_request
{required string mobile  = 1;    // 手机号码required int32  amount  = 2;    // 充值金额
}message recharge_response
{required int32   code   = 1;    // 响应代号optional string  desc   = 2;    // 验证码required int32  balance = 3;    // 最新的余额
}message account_balance_request
{required string mobile = 1;
}message account_balance_response
{required int32   code   = 1;    // 响应代号optional string  desc   = 2;    // 验证码required int32  balance = 3;
}message list_account_records_request
{required string mobile = 1;
}message list_account_records_response
{required int32   code   = 1;    // 响应代号optional string  desc   = 2;    // 验证码message account_record{required int32  type      = 1; // 0 : 骑行消费,  1 : 充值, 2 : 退款required int32  limit     = 2; // 消费或者充值金额required uint64 timestamp = 3; // 记录发生时的时间戳}repeated account_record records = 3;
}message list_travel_records_request
{required string mobile = 1;
}message list_travel_records_response
{required int32   code   = 1;    // 响应代号optional string  desc   = 2;    // 验证码message travel_record{required uint64 stm      = 1;   // start timestamprequired uint32 duration = 2;   // 骑行时长required uint32 amount   = 3;   // 所耗金额}required double              mileage   = 3; // 里程required double              discharge = 4; // 排放required double              calorie   = 5; // 卡路里repeated travel_record       records   = 6;
}

编译message文件

编译语法:

protoc -I=$SRC_DIR --cpp_out=$DST_DIR  bike.proto

SRC_DIR 表示proto文件所在的目录,cpp_out指定了生成的代码的路径, bike.proto指proto文件名。

protoc -I=./ --cpp_out=./ bike.proto

这样在当前目录生成了bike.pb.cc和bike.pb.h两个文件。

编译生成的c++文件 

g++  -std=c++11   example.cc bike.pb.cc -lprotobuf

应用protobuf

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

API说明  : https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.message

  • Message 基本用法

范例1: example1.cc

#include "bike.pb.h"
#include <string>
#include <iostream>using namespace std;
using namespace tutorial;int main(void)
{std::string data;   //存储序列化的消息//客户端发送请求{mobile_request mr;mr.set_mobile("18684518289");mr.SerializeToString(&data);cout<<"序列化后的数据["<<data.length()<<"]: "<< data << endl;cout<<hex<<(int)*((char*)data.c_str())<<endl;cout<<hex<<(int)*((char*)data.c_str() + 1)<<endl;//客户端发送data  send(sockfd, data.c_str(), data.length());}//服务器端接受请求{//receive(sockfd, data, ...);mobile_request mr;mr.ParseFromString(data);cout<<"客户端手机号码: " << mr.mobile() << endl;}return 0;
}
  • Message 嵌套使用

范例2: example1.cc

#include "bike.pb.h"
#include <string>
#include <iostream>using namespace std;
using namespace tutorial;int main(void)
{std::string data;   //存储序列化的消息//客户端发送请求{list_account_records_response larr;larr.set_code(200);larr.set_desc("ok");for(int i=0; i<5; i++){list_account_records_response_account_record * ar = larr.add_records();ar->set_type(0);ar->set_limit(i * 100);ar->set_timestamp(time(NULL));}printf("recoreds size : %d\\n", larr.records_size());larr.SerializeToString(&data);//客户端发送data  send(sockfd, data.c_str(), data.length());}//服务器端接受请求{list_account_records_response larr;larr.ParseFromString(data);printf("recoreds size : %d\\n", larr.records_size());printf("code: %d\\n", larr.code());for(int i=0; i<larr.records_size(); i++){const list_account_records_response_account_record &ar = larr.records(i);printf("limit: %d\\n", ar.limit());}//cout<<"客户端手机号码: " << mr.mobile() << endl;}return 0;
}