我是靠谱客的博主 幸福服饰,这篇文章主要介绍Protobuf 的简单使用例子,现在分享给大家,希望可以做个参考。

文章目录

    • 应用层协议设计
      • protobuf 序列化
        • protobuf的原理
        • 定义message
        • 编译message文件
        • 应用protobuf
        • Message 基本用法
        • Message 嵌套使用
      • 具体操作


点击我, 到底部

应用层协议设计

  • 通信双方交换数据的格式与顺序
  • 通信双方应该采取的动作

用户登陆模块

  • 短信获取
    获取短信请求 mobile_request
字段名类型属性字段描述
mobilestringrequired手机号码, 必须为大陆手机取 11 位数字

获取短信响应 mobile_response

字段名类型属性字段描述
codeint32required响应代号: 200-成功 400-失败
icodeint32required成功保存验证码, 失败保存0
descstringoptional可选, 失败时描述失败原因

登陆验证

  • 短信验证请求 login_request
字段名类型属性字段描述
mobilestringrequired手机号码, 必须为大陆手机取 11 位数字
icodeint32required验证码
  • 短信验证响应 login_response
字段名类型属性字段描述
codeint32required响应代号: 200-成功 400-失败
descstringoptional可选, 失败时描述失败原因

充值

  • 充值请求 recharge_request
字段名类型属性字段描述
mobilestringrequired手机号码, 必须为大陆手机取 11 位数字
amountint32required充值数量
  • 充值响应 recharge_response
字段名类型属性字段描述
codeint32required响应代号: 200-成功 400-失败
descstringoptional可选, 失败时描述失败原因
balanceint32required最新余额
  • 余额查询 account_balance_request
字段名类型属性字段描述
mobilestringrequired手机号码, 必须为大陆手机取 11 位数字
  • 余额查询响应 account_balance_response
字段名类型属性字段描述
codeint32required响应代号: 200-成功 400-失败
descstringoptional可选, 失败时描述失败原因
balanceint32required失败置为 -1

查询充值记录

  • 充值记录请求 list_account_records_request
字段名类型属性字段描述
mobilestringrequired手机号码, 必须为大陆手机取 11 位数字
  • 充值记录响应 list_account_records_response
字段名类型属性字段描述
codeint32required响应代号: 200-成功 400-失败
descstringoptional可选, 失败时描述失败原因
recordsaccount_recordrequired==>>

==>>

复制代码
1
2
3
4
5
6
message account_record { required int32 type = 1; // 0 : 骑行消费, 1 : 充值, 2 : 退款 required int32 limit = 2; // 消费或者充值金额 required uint64 timestamp = 3; // 记录发生时的时间戳 }

查询骑行记录

  • 骑行记录查询请求 list_travel_records_request
字段名类型属性字段描述
codeint32required手机号码, 必须为大陆手机取 11 位数字
  • 骑行记录查询响应 list_travel_records_response
字段名类型属性字段描述
codeint32required响应代号: 200-成功 400-失败
descstringoptional可选, 失败时描述失败原因
recordstravel_recordrequiredxxx
mileagedoublerequired骑行里程
dischargedoublerequired排放
caloriedoublerequired卡路里

xxx

复制代码
1
2
3
4
5
6
7
8
9
message travel_record { required uint64 stm = 1; // start timestamp required uint32 duration = 2; // 骑行时长 required uint32 amount = 3; // 所耗金额 }

protobuf 序列化

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

protobuf官网

请科学上网

protobuf的原理

在这里插入图片描述
protobuf 的安装

复制代码
1
2
3
4
5
6
7
8
9
10
11
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文件

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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文件

编译语法:

复制代码
1
2
protoc -I=$SRC_DIR --cpp_out=$DST_DIR bike.proto

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

复制代码
1
2
protoc -I=./ --cpp_out=./ bike.proto

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

编译生成的c++文件

复制代码
1
2
g++ --std=c++11 example.cc bike.pb.cc -lprotobuf

应用protobuf

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

API说明

Message 基本用法

范例1: example1.cc

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#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

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#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内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(67)

评论列表共有 0 条评论

立即
投稿
返回
顶部