PB协议应用说明

一、目的

本文档记录PB协议使用的过程。

二、工具准备

  1. nanopb工具:nanopb-0.3.8-windows-x86

三、应用说明

3.1 PB协议语法说明

1)google官网PB协议指导:

https://developers.google.cn/protocol-buffers/docs/proto?hl=zh-cn#options

2)”看,未来”博主的文档:

https://blog.51cto.com/u_15197573/2772508#import_99

3)PB协议相关函数说明:

https://jpa.kapsi.fi/nanopb/docs/reference.html#pb_encode_tag_for_field

3.2 编译

编写proto文件和options文件后,进入nanopb-0.3.8-windows-x86\generator-bin,打开命令行,输入以下命令。

protoc --nanopb_out=. test.proto

其中test.proto改成所需的文件名称。

输入该命令后,会生成对应的c和h文件,如图 1。

 

图 1 编译生成的文件

3.3 应用

3.3.1 搭建工程

添加中图 2的文件和编译生成的文件到工程中。

 

图 2 PB协议相关文件

添加图 3的头文件以及编译生产的头文件。

图 3 PB协议相关头文件

3.3.2 字段赋值

1)字段规则为”required”或”optional”,并且字段长度固定时,相应字段直接赋值,参考以下示例。

代码 1 proto文件配置

syntax = "proto2";

message sub

{

required int32 a = 1;

optional int32 b = 2;

}

message TreadReq

{

required sub dat1 = 1;

required int32 dat2 = 2;

optional string dat3 = 3;

}

代码 2 options文件配置

TreadReq.dat3 max_size:5    //设置长度

代码 3 生成的代码

/* Struct definitions */

typedef struct _sub {

    int32_t a;

    bool has_b;

    int32_t b;

/* @@protoc_insertion_point(struct:sub) */

} sub;

typedef struct _TreadReq {

    sub dat1;

    int32_t dat2;

    bool has_dat3;

    char dat3[5];

/* @@protoc_insertion_point(struct:TreadReq) */

} TreadReq;

代码 4 字段赋值

TreadReq tread;

tread.dat1.a = 10;

tread.dat1.has_b = true;

tread.dat1.b = 10;

tread.dat2 = 10;

tread.has_dat3 = true;

memcpy(tread.dat3,"12345",5);

  1. 字段规则为”repeated”或不固定长度,使用回调函数赋值,参考以下示例。

代码 5 proto文件配置

syntax = "proto2";

message TreadReq

{

required string dat1 = 1;

repeated int32 dat2 = 2;

}

代码 6 生成的代码

/* Struct definitions */

typedef struct _TreadReq {

    pb_callback_t dat1;

    pb_callback_t dat2;

/* @@protoc_insertion_point(struct:TreadReq) */

} TreadReq;

代码 7 字段赋值

bool dat1_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)

{

if (!pb_encode_tag_for_field(stream, field))  //开始一个字段的赋值

{

return false;

}

if(!pb_encode_string(stream, (const pb_byte_t *)str, 12 )) //写入12个字节

{

return false;

}

}

bool dat2_callback(pb_ostream_t *stream, const pb_field_t *field, void * const *arg)

{

uint8_t i = 0;

for(i = 0; i < 20; i++)  //repeated字段,重复赋值

{

if (!pb_encode_tag_for_field(stream, field))  //开始一个字段的赋值

{

return false;

}

if(!pb_encode_varint(stream, dat[i])) //赋值

{

return false;

}

}

}

int main()

{

TreadReq tread;

tread.dat1.funcs.encode = &dat1_callback;  //使用回调函数赋值

tread.dat1.arg = NULL;

tread.dat2.funcs.encode = &dat1_callback;  //使用回调函数赋值

tread.dat2.arg = NULL;

}

3.3.3 数据编码encode

数据编码要使用pb_ostream_from_buffer()和pb_encode()。pb_ostream_from_buffer()用于指定缓存区,pb_encode()用于数据编码,具体说明参考PB协议相关函数说明。以代码 4为基础,进行数据编码,如代码 8。其中TreadReq_fields与TreadReq对应。

代码 8 数据编码

uint8_t buffer[100];  //协议数据缓存区,使用该缓存区发送协议数据

pb_ostream_t stream

TreadReq tread;

tread.dat1.a = 10;

tread.dat1.has_b = true;

tread.dat1.b = 10;

tread.dat2 = 10;

tread.has_dat3 = true;

memcpy(tread.dat3,"12345",5);

stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); //指定缓存区

pb_encode(&stream, TreadReq_fields, &tread); //编码

3.3.4 数据解码decode

数据解码需要使用pb_istream_from_buffer()和pb_decode()。pb_istream_from_buffer()用于指定解码缓存区,pb_decode()用于数据解码。

  1. 字段规则为requiredoptional,并且字段长度固定时,可以直接使用对应字段的值。以3.3.2 1)为基础,进行数据解码,如代码 9

代码 9 数据解码

void my_pb_decode(uint8_t *buf,uint32_t len)

{

TreadReq tread;

pb_istream_t istream;

istream = pb_istream_from_buffer(buf, len); //指定解码缓存区

pb_decode(&istream, TreadReq_fields, &tread); //解码

 //规则为"required"时,直接使用字段的值

printf("required:%d,%d\r\n",tread.dat1.a,tread.dat2);

if(tread.dat1.has_b)

{

         //规则为"optional"时,先判断是否存在该字段,再使用该值

printf("optional:%d\r\n",tread.dat1.b);         

}

if(tread.has_dat3)

{

for(int i = 0; i < 5; i++)

{

              //规则为"optional"且长度固定时,先判断是否存在该字段,再使用该值

printf("%d ",tread.dat3[i]);              

}

}

}

  1. 字段规则为repeated或者不定长度时,使用回调函数进行解码。以3.3.2 2)为基础,进行解码,如代码 10

代码 10 数据解码

static bool read_repeated_string(pb_istream_t* stream, const pb_field_t* field, void** arg)

{

uint8_t*** expected = (uint8_t***)arg;

size_t len = stream->bytes_left;

if (!pb_read(stream, (uint8_t *)(*expected)++, len))

return false;

return true;

}

static bool read_repeated_varint(pb_istream_t* stream, const pb_field_t* field, void** arg)

{

int32_t** expected = (int32_t**)arg;

uint64_t value;

if (!pb_decode_varint(stream, &value))

return false;

*(*expected)++ = value;

return true;

}

void my_pb_decode(uint8_t *buf,uint32_t len)

{

TreadReq tread;

pb_istream_t istream;

char str[10][100] = {0};//repeated规则,string类型,需要二维数组保存解码数据

int32_t dat[10] = {0};//repeated规则,int32类型,需要一维数组保存解码数据

tread.dat1.funcs.decode = read_repeated_string;  //使用回调函数解码

tread.dat1.arg = str;

tread.dat2.funcs.decode = &read_repeated_varint; //使用回调函数解码

tread.dat2.arg = dat;

istream = pb_istream_from_buffer(buffer, stream.bytes_written); //指定缓存区

pb_decode(&istream, TreadReq_fields, &tread); //解码

//使用解码数据

printf("str:%s\r\n", str[0]);

printf("buf:%d,%d,%d,%d,%d\r\n", dat[0], dat[1], dat[2], dat[3], dat[4]);

}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PermissionBase权限管理系统0.1.2源码 1.概述Permission Base(授权基础,以下简称PB)是一个基于.NET 2.0平台开发的开源项目,使用的协议为:Apache License Version 2.0。 PB是一套适用于一般中小型B/S企业应用系统的“权限控制基础结构”。PB的定位并不是一个通用的组件或者框架,而是一个“半成品的程序”。它包含了一个适用于一般企业应用系统的框架,以及与用户权限管理相关的结构和模块,因此PB可以作为中小型企业应用系统或一般网站系统的实现参考或者项目雏形。 PB包括以下模块:职员登录、模块导航、系统代码管理、模块管理、角色管理、部门管理、职员管理、修改密码、前台用户信息管理。这些功能和模块是大多数企业应用系统中所必须的。 2.适用范围序号 描述 1 PB目前的版本被设计为仅能在单台服务器上运行。 2 PB并不适用于分布式的情况,即所有的横向分层(表现层,服务层,业务逻辑层,数据访问层,……)都仅设计为逻辑的分层,而不是物理的分层,各层只能部署在一台服务器上运行。 3 PB也并不是集群系统,即不能在集群环境下部署,这主要是因为目前使用的缓存策略导致的。 3.使用的技术、工具和产品开发平台 .NET 2.0.50727 IDE Visual Studio 2005 Pro/Team UML设计 Sybase PowerDesigner 12 项目文件夹结构目录 说明 doc 项目文档 lib 项目引用到的第三方程序集(dll) model / oom UML图 model / pdm 数据库设计文档(E – R图) model / sql 数据库创建和删除的脚本 resource 项目使用到的第三方UI控件的完整源码包 描述 1 “职员”和“用户”的登录密码在存入数据库前都进行了SHA1加密。 2 登录时的验证码在放入cookie前进行了DES加密。 3 由于所有的页面跳转全部使用的是相对路径,所以不能对单独的某几个包含密码信息的页面使用SSL。可以对整个Admin目录使用SSL。但如果觉得这样做带来的性能损失太大,则必须重构相关页面跳转的代码。
HTTP协议是一种应用协议,用于在Web浏览器和Web服务器之间传输数据。而Protocol BufferPB)是一种轻便高效的数据交换格式,通常用于数据序列化和反序列化。PB可以用于各种语言和平台,并且可以在不同的应用程序之间进行数据交换。在HTTP协议中,PB可以用作数据格式,以便在客户端和服务器之间传输数据。 PB协议的基本使用和格式定义可以参考引用中的内容。在HTTP协议中,PB通常用作请求和响应的数据格式。客户端代码可以使用HTTP库(如Python中的requests库)向服务器发送请求,并将PB格式的数据作为请求体发送。服务器可以解析请求体中的PB数据,并使用PB格式的数据作为响应体返回给客户端。 以下是一个使用Python的requests库向服务器发送PB格式数据的示例代码: ```python import requests import addressbook_pb2 # 创建一个Person对象 person = addressbook_pb2.Person() person.id = 1234 person.name = "John Doe" person.email = "[email protected]" phone = person.phones.add() phone.number = "555-4321" phone.type = addressbook_pb2.Person.HOME # 将Person对象序列化为二进制数据 data = person.SerializeToString() # 发送POST请求,将PB格式数据作为请求体发送 response = requests.post('http://example.com/api/person', data=data) # 解析响应体中的PB格式数据 person2 = addressbook_pb2.Person() person2.ParseFromString(response.content) print(person2.name) # 输出:John Doe ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值