我是靠谱客的博主 幸福服饰,最近开发中收集的这篇文章主要介绍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==>>

==>>

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

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 的简单使用例子所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部