概述
文章目录
- 应用层协议设计
- protobuf 序列化
- protobuf的原理
- 定义message
- 编译message文件
- 应用protobuf
- Message 基本用法
- Message 嵌套使用
- 具体操作
点击我, 到底部
应用层协议设计
- 通信双方交换数据的格式与顺序
- 通信双方应该采取的动作
用户登陆模块
- 短信获取
获取短信请求mobile_request
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
mobile | string | required | 手机号码, 必须为大陆手机取 11 位数字 |
获取短信响应 mobile_response
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
code | int32 | required | 响应代号: 200-成功 400-失败 |
icode | int32 | required | 成功保存验证码, 失败保存0 |
desc | string | optional | 可选, 失败时描述失败原因 |
登陆验证
- 短信验证请求
login_request
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
mobile | string | required | 手机号码, 必须为大陆手机取 11 位数字 |
icode | int32 | required | 验证码 |
- 短信验证响应
login_response
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
code | int32 | required | 响应代号: 200-成功 400-失败 |
desc | string | optional | 可选, 失败时描述失败原因 |
充值
- 充值请求
recharge_request
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
mobile | string | required | 手机号码, 必须为大陆手机取 11 位数字 |
amount | int32 | required | 充值数量 |
- 充值响应
recharge_response
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
code | int32 | required | 响应代号: 200-成功 400-失败 |
desc | string | optional | 可选, 失败时描述失败原因 |
balance | int32 | required | 最新余额 |
- 余额查询
account_balance_request
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
mobile | string | required | 手机号码, 必须为大陆手机取 11 位数字 |
- 余额查询响应
account_balance_response
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
code | int32 | required | 响应代号: 200-成功 400-失败 |
desc | string | optional | 可选, 失败时描述失败原因 |
balance | int32 | required | 失败置为 -1 |
查询充值记录
- 充值记录请求
list_account_records_request
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
mobile | string | required | 手机号码, 必须为大陆手机取 11 位数字 |
- 充值记录响应
list_account_records_response
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
code | int32 | required | 响应代号: 200-成功 400-失败 |
desc | string | optional | 可选, 失败时描述失败原因 |
records | account_record | required | ==>> |
==>>
message account_record {
required int32 type = 1; // 0 : 骑行消费, 1 : 充值, 2 : 退款
required int32 limit = 2; // 消费或者充值金额
required uint64 timestamp = 3; // 记录发生时的时间戳
}
查询骑行记录
- 骑行记录查询请求
list_travel_records_request
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
code | int32 | required | 手机号码, 必须为大陆手机取 11 位数字 |
- 骑行记录查询响应
list_travel_records_response
字段名 | 类型 | 属性 | 字段描述 |
---|---|---|---|
code | int32 | required | 响应代号: 200-成功 400-失败 |
desc | string | optional | 可选, 失败时描述失败原因 |
records | travel_record | required | xxx |
mileage | double | required | 骑行里程 |
discharge | double | required | 排放 |
calorie | double | required | 卡路里 |
xxx
message travel_record {
required uint64 stm = 1;
// start timestamp
required uint32 duration = 2;
// 骑行时长
required uint32 amount = 3;
// 所耗金额
}
protobuf 序列化
protobuf是一种比json和xml等序列化工具更加轻量和高效的结构化数据存储格式,
性能比json和xml真的强很多,毕竟google出品。
protobuf官网
请科学上网
protobuf的原理
protobuf 的安装
apt-get install autoconf automake libtool curl make g++ unzip
$ 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
定义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 timestamp
required 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说明
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 : %dn", 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 : %dn", larr.records_size());
printf("code: %dn", larr.code());
for(int i=0; i<larr.records_size(); i++)
{
const list_account_records_response_account_record &ar = larr.records(i);
printf("limit: %dn", ar.limit());
}
//cout<<"客户端手机号码: " << mr.mobile() << endl;
}
return 0;
}
具体操作
第一步新建一个, bike.proto 文件
第二步: 编译
生成文件
和.cc 整合
运行结果
第二个例子, 就不具体操作了
点击我, 到顶部最后
以上就是幸福服饰为你收集整理的Protobuf 的简单使用例子的全部内容,希望文章能够帮你解决Protobuf 的简单使用例子所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复