protobuf基础学习

部分内容出自:https://blog.csdn.net/baidu_32237719/article/details/99723353
proto文件来预先定义的消息格式。数据包是按照proto文件所定义的消息格式完成二进制码流的编码和解码。proto文件,简单地说,就是一个消息的协议文件,这个协议文件的后缀文件名为“.proto”。proto其实就相当于接口的调用,类似于post,get等这些请求于响应处理,它也会携带信息输出,类似于请求头,请求头…

基础语法:

// 声明使用的语法是proto3,否则默认是proto2,一般写于第一行

syntax = "proto3";

拍//命名空间,包名,必须第二行

package google.protobuf;

//导包
如果想使用的消息类型定义在另一个.proto文件中,可以通过导包的方式将另一个文件导入进来,导包的语句如下:

import "google/protobuf/source_context.proto";

导入某个包,上面导入了source_context包,就可以支持Protobuf3的SourceContext类型。
例:test.proto中调用test2.proto文件中的DeviceInfo这个message,test2.proto的包名是 test2package
(1)import “test2.proto”; 添加你需要调用哪一个proto文件
(2)在test.proto中调用: test2package.DeviceInfo deviceInfo = 2;

syntax = "proto3";
package testpackge;
import "test2.proto"//导入test2.proto包
message Info{string id = 1;//调用Messagetest2package.DeviceInfo deviceInfo = 2;
}

//option可选项
//是否运行生成多个java文件

option java_multiple_files = false;

//这个选项表明生成java类所在的包。如果在.proto文件中没有明确的声明java_package,就采用默认的包名

option java_package = “com.example.administrator.grpctest.proto”;

//生成的java类名字

option java_outer_classname = “TestProto”;

//生成方式:可以被设置为 SPEED, CODE_SIZE,or LITE_RUNTIME。这些值将通过如下的方式影响C++及java代码的生成:

option optimize_for = SPEED;

① SPEED(默认值):
表示生成的代码运行效率高,但是由此生成的代码编译后会占用更多的空间。
② CODE_SIZE:
与SPEED恰恰相反,代码运行效率较低,但是由此生成的代码编译后会占用更少的空间,
通常用于资源有限的平台,如Mobile。
③ LITE_RUNTIME:
生成的代码执行效率高,同时生成代码编译后的所占用的空间也非常少。
这是以牺牲Protobuf提供的反射功能为代价的。
因此我们在C++中链接Protobuf库时仅需链接libprotobuf-lite,而非protobuf。
//1. SPEED模式:(自定义的类继承自 Message 类)
// .proto 文件:
option optimize_for = SPEED;
// .pb.h 文件:
class Person : public ::PROTOBUF_NAMESPACE_ID::Message {};
//2. CODE_SIZE模式:(自定义的类继承自 Message 类)
// .proto 文件:
option optimize_for = CODE_SIZE;
// .pb.h 文件:
class Person : public ::PROTOBUF_NAMESPACE_ID::Message {};
//3. LITE_RUNTIME模式:(自定义的类继承自 MessageLite 类)
// .proto 文件:
option optimize_for = LITE_RUNTIME;
// .pb.h 文件:
class Person : public ::PROTOBUF_NAMESPACE_ID::MessageLite {};

// 需要传输的数据格式
//定义消息:消息的结构体,以message标识。
格式顺序为:修饰符 参数类型 参数名字 = 标识符 [默认值]

message Api {string name = 1;repeated Method methods = 2;repeated Option options = 3;string version = 4;SourceContext source_context = 5;repeated Mixin mixins = 6 default = 123];        //数组Syntax syntax = 7;
}

//一个proto文件可以定义多个数据格式

enum FctaFrntLeWarnReq {FCTA_FRNT_LEFT_NO_WARNING       = 0;FCTA_FRNT_LEFT_WARNING_LEVEL_1  = 1;FCTA_FRNT_LEFT_WARNING_LEVEL_2  = 2;FCTA_FRNT_LEFT_WARNING_RESERVED = 3;
}

//也可以在数据格式里面嵌套另一个数据格式

message Info{
string name = 1;int age = 2;
Int sex = 3;
Job job = 4;
}
message Job{
string job = 1;
}

//字段规则 required : 字段只能也必须出现 1 次,多用于必填项,必须赋值的字符

required int32 id = 1 [default = 123]

//optional : optional #结合message使用,表示message字段的内容选填,可以传也可以不传,可以使用[default = xxx]配置默认值 例如:

optional string name = 1 [default = "张三"]

//repeated :#结合message使用,表示该字段接收或返回为数组,字段可出现任意多次(包括 0)
多用于 Java List 属性 例如:

//list String
repeated string strList = 5;
//list 对象
repeated Role roleList = 6;

//定义接口:接口路径和参数,以service标识。
#定义这个proto文件的方法集合,类似于方法接口
(1) 定义访问服务端的函数名称,传递参数,返回值
— 就是rpc通信中构建请求消息结构的 接口名称
(2) 一个service可以定义多个待调用的函数
(3) 定义方式:rpc 方法名 (参数) returns (返回值) 没有返回值 就写Empty
rpc #定义方法的关键字,结合service使用
returns #返回响应,结合service使用

service FctaAdBlindZoneFuncMgr {option(service_id) = 9008;rpc FctaOnOffSetMed(FctaOnOffSetMsg) returns (Null) {option (rpc_id) = 102;option (method_type) = METHOD;}rpc FctaWarnReqEvt(FctaWarnReqMsg) returns (Null) {option (rpc_id) = 100;option (method_type) = EVENT;option (update_policy) = ON_CHANGE;}rpc FctaOnOffStsFid(FctaOnOffStsMsg) returns (Null) {option (rpc_id) = 101;option (method_type) = FIELD_READONLY;option (update_policy) = ON_CHANGE;}
}

//保留标识符(reserved)

message Persion{string id = 1;string name = 2;//保留3,15,9,10,11这几个标识符不能被使用reserved  3, 15, 9 to 11;//reserved "location"
}

//emnu格式定义

  enum Corpus {UNIVERSAL = 0;WEB = 1;IMAGES = 2;LOCAL = 3;NEWS = 4;PRODUCTS = 5;VIDEO = 6;}

//可以将option属性中allow_alias 设置为true,来为枚举类型定义相同的常量值

  enum EnumAllowingAlias {option allow_alias = true;UNKNOWN = 0;STARTED = 1;RUNNING = 1;}

枚举常量值必须在32字节integer范围内。负数效率低,不推荐使用
//枚举嵌入在message中是不带标识符的

message SearchRequest {string query = 1;int32 page_number = 2;int32 result_per_page = 3;enum Corpus {UNIVERSAL = 0;WEB = 1;IMAGES = 2;LOCAL = 3;NEWS = 4;PRODUCTS = 5;VIDEO = 6;}Corpus corpus = 4;
}

枚举定义在一个消息内部或消息外部都是可以的,如果枚举是 定义在 message 内部,而其他 message 又想使用,那么可以通过 MessageType.EnumType 的方式引用。定义枚举的时候,我们要保证第一个枚举值必须是0,枚举值不能重复,除非使用 option allow_alias = true 选项来开启别名。

enum EnumAllowingAlias {option allow_alias = true;UNKNOWN = 0;STARTED = 1;RUNNING = 1;
}

//map类型
map<key_type, value_type> map_field = N;1
其中key_type可以是任意Integer或者string类型(所以,除了floating和bytes的任意标量类型都是可以的)value_type可以是任意类型。

例如,如果你希望创建一个project的映射,每个Projecct使用一个string作为key,你可以像下面这样定义:

map<string, Project> projects = 3;

**

示例:

**
定义xxx.proto

syntax = "proto3";// 声明是为了防止不同项目之间的命名冲突,编译生成的类将被放置在一个与 package 名相同的命名空间中。
package tutorial;message Student {// 字段编号:消息定义中的每个字段都有一个唯一的编号。这些字段编号用于以二进制格式标识您的字段,一旦您的消息类型被使用,就不应该被更改uint64 id = 1;string name = 2;// singular修饰符修饰的字段可以是0次或者1次。但是当定制协议,用该修饰符修饰的字段都报错// singular string email = 3;string email = 3;enum PhoneType {MOBILE         = 0; //proto3版本中,首成员必须为0,成员不应有相同的值HOME         = 1;}message PhoneNumber {string number         = 1;PhoneType type = 2;}// repeated: 该字段可以重复任意次数(包括零次)。重复值的顺序将被保留repeated PhoneNumber phone = 4;
}

在这里插入图片描述解析出.cc和.h文件

protoc proto文件路径 --cpp_out=C++代码文件导出目录

Protobuf数据写入和读取

#include "test.pb.h"		//解析出来的.h文件
#include "stdio.h"void sendHeart();
void receHeart(TopMessage* topMessage);
void receHeartResp(TopMessage* topMessage);/*
** ===================================================================
**     Method      :  sendHeart 
**
**     Description :  数据写入
** 
** ===================================================================
*/
void sendHeart(){TopMessage message;message.set_message_type(REQUEST_HEARTBEAT_SIGNAL);printf("sendHeart %d\n",message.message_type());receHeart(&message);
}/*
** ===================================================================
**     Method      :  receHeart 
**
**     Description :  数据读取然后写入
** 
** ===================================================================
*/
void receHeart(TopMessage* topMessage){if (topMessage->message_type() == REQUEST_HEARTBEAT_SIGNAL){printf("request_heartbeat_signal\n");TopMessage topMessageResp;MsgResult mesResult;mesResult.set_result(true);mesResult.set_error_code("error");topMessageResp.set_message_type(RESPONSE_HEARTBEAT_RESULT);*topMessageResp.mutable_msg_result() = mesResult;receHeartResp(&topMessageResp);}}/*
** ===================================================================
**     Method      :  receHeartResp 
**
**     Description :  数据读取
** 
** ===================================================================
*/
void receHeartResp(TopMessage* topMessage){if (topMessage->message_type() == RESPONSE_HEARTBEAT_RESULT){printf("response_heartbeat_result\n");printf("%s\n",topMessage->msg_result().error_code().c_str());}
}int main()
{sendHeart();google::protobuf::ShutdownProtobufLibrary();//删除所有已分配的内存(Protobuf使用的堆内存)
}

先进行数据写入,然后数据读取,根据读取到的数据,进行数据写入,最后再读取验证。
整个Demo很简单,包含了数据的读取和写入基本操作
详细的读取和写入方式还请自行查找相关文档或访问官网,我这里由于官网需要翻墙无法访问,且c++水平有限,仅通过解码后的.cc 和 .h进行推测

编译

g++ -std=c++11 test.pb.cc test.cpp -o test `pkg-config --cflags --libs protobuf`

test.pb.cc为解析出来的.cc源文件
test.cpp为编写Demo的源文件
-std=c++11 需要ISO C++ 2011 standard 支持,必须加,否则会报下列错误,编译无法通过

执行

./test
//输出
sendHeart 1
request_heartbeat_signal
response_heartbeat_result
error

//Protobuf API,读写类,编译器为每个字段生成读写函数

  // optional uint64 id = 1;void clear_id();static const int kIdFieldNumber = 1;::google::protobuf::uint64 id() const;void set_id(::google::protobuf::uint64 value);// optional string name = 2;void clear_name();static const int kNameFieldNumber = 2;const ::std::string& name() const;void set_name(const ::std::string& value);void set_name(const char* value);void set_name(const char* value, size_t size);::std::string* mutable_name();::std::string* release_name();void set_allocated_name(::std::string* name);// optional string email = 3;void clear_email();static const int kEmailFieldNumber = 3;const ::std::string& email() const;void set_email(const ::std::string& value);void set_email(const char* value);void set_email(const char* value, size_t size);::std::string* mutable_email();::std::string* release_email();void set_allocated_email(::std::string* email);// repeated .tutorial.Student.PhoneNumber phone = 4;int phone_size() const;void clear_phone();static const int kPhoneFieldNumber = 4;const ::tutorial::Student_PhoneNumber& phone(int index) const;::tutorial::Student_PhoneNumber* mutable_phone(int index);::tutorial::Student_PhoneNumber* add_phone();::google::protobuf::RepeatedPtrField< ::tutorial::Student_PhoneNumber >* mutable_phone();const ::google::protobuf::RepeatedPtrField< ::tutorial::Student_PhoneNumber >&phone() const;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/217573.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git常用命令大全

1.强制推送&#xff08;慎用&#xff0c;除非你认为其他冲突等可以丢弃 或者不是很重要&#xff09; git push -- force2.创建文件等小命令 touch a // 创建一个a文件 echo 1234 >> a // 把1234这个内容放入a文件 cat a // 打开a文件 读取出a文件中的内容 mkdir test /…

MAC IDEA Maven Springboot

在mac中&#xff0c;使用idea进行maven项目构建 环境配置如何运行maven项目1.直接在IDEA中运行2.使用jar打包后执行 如何搭建spring boot1.添加依赖2.创建入口类3.创建控制器4. 运行5.其他 环境配置 官网安装IDEA使用IDEA的创建新项目选择创建MAEVEN项目测试IDEA的MAVEN路径是…

(第64天)UNPLIUG/PLUG 迁移 PDB

在 Oracle 12C 之前,迁移数据库的方式大多通过 RMAN 或者数据泵的方式,但是在 12C 版本提出 CDB/PDB 架构后,对数据库进行了整合,只需要针对 PDB 进行迁移即可,本文介绍通过 UNPLUG/PLUG 的方式来迁移数据库。 环境信息 测试环境信息: 角色主机名IP地址数据库版本实例名…

【二分查找】【双指针】LeetCode:2565最少得分子序列

作者推荐 【动态规划】【广度优先】LeetCode2258:逃离火灾 本文涉及的基础知识点 二分查找算法合集 有序向量的二分查找&#xff0c;初始化完成后&#xff0c;向量不会修改。 双指针&#xff1a; 用于计算子字符串是s的字符串的子系列。 题目 给你两个字符串 s 和 t 。 你…

《地理信息系统原理》笔记/期末复习资料(10. 空间数据挖掘与空间决策支持系统)

目录 10. 空间数据挖掘与空间决策支持系统 10.1. 空间数据挖掘 10.1.1. 空间数据挖掘的概念 10.1.2. 空间数据挖掘的方法与过程 10.1.3. 空间数据挖掘的应用 10.2. 空间决策支持系统 10.2.1. 空间决策支持系统的概念 10.2.2. 空间决策支持系统的结构 10.2.3. 空间决策…

Java网络编程,使用UDP实现TCP(二), 实现数据传输过程

简介&#xff1a; 经过了三次握手过程&#xff0c;我们的服务端和客户端已经建立了连接。我们接下来需要做的就是数据的传输。 主要步骤&#xff1a; 数据发送&#xff1a;客户端或服务器将数据打包成一个或多个数据段&#xff0c;每个数据段都有一个序列号&#xff08;SEQ&a…

mybatis xml 热部署

平时我们在项目中多多少少会根据不同的情况等等原因去调试sql&#xff0c;在数据库测试完后也需要在代码里面运行测试&#xff0c;但是每次修改就需要重启服务就显得太繁琐&#xff0c;所以如果mybatis的xml也可以热部署当然是最好的了&#xff0c;那我来试试如何可以将mybatis…

pytorch-0.4.0上古版本安装参考

由于pytorch previous-versions中已经不显示该版本&#xff0c;而且网络上信息很少&#xff0c;配环境给我配麻了&#xff0c;所以提供一个参考。 我的配置&#xff1a; cuda 9.0 gcc 4.8.5 安装过程&#xff1a; conda create -n torch040 python3.6.6 conda install pytorc…

C++ 学习系列 -- conversion function

一 什么是转换函数&#xff1f; 在 c 编码中&#xff0c;我们可能遇到要将类 A 转为 类 B 的情况&#xff0c;此时就可以定义类 A 的转换函数将其按照一定规则转换为 类 B&#xff1b; 转换函数声明规则如下&#xff1a; operator 转换类型() const; 转换函数无返回值&#x…

基于chaos混沌的彩色图像加解密系统matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 混沌理论简介 4.2 基于混沌的图像加密原理 4.3 数学公式与实现过程 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .................…

记录将C语言编写的Windows程序转换为python语言编写,演示具体效果在最后,这对初学者理解Windows消息机制及框架有一定参考作用

主要思路 由于C语言的数组定义使用名字加中括号及括号内数字定义&#xff0c;但是在python中【】已经被作为列表 元组等序列类型分片、存取元素&#xff0c;因此我们不能像C语言那样定义数组 例如C语言 int a[10] 是声明定义一个含有10个int类型的数组a,而在执行语句部分…

Android基础:使用Intent意图类 和 Bundle类对安卓页面Activity页面进行数据的传递 实现Activity页面之间通信技术

Android Intent 和 Bundle与Activity之间的通信 下面是Android基础&#xff1a;使用Intent意图类 和 Bundle类对安卓页面Activity页面进行数据的传递 && 实现Activity页面之间通信技术 ** 实现的目的 **&#xff1a;页面之间的数据传输&#xff0c;通过将数据打包传递…

华为OD机试真题B卷 Java 实现【统计大写字母个数】,附详细解题思路

一、题目描述 找出给定字符串中大写字符(即’A’-‘Z’)的个数。 数据范围&#xff1a;字符串长度&#xff1a;1≤∣s∣≤250 字符串中可能包含空格或其他字符 二、输入描述 对于每组样例&#xff0c;输入一行&#xff0c;代表待统计的字符串。 三、输出描述 输出一个整…

【1day】​万户协同办公平台 iSignatureHTML.jsp/DocumentEdit.jsp 文件SQL注入漏洞学习

注:该文章来自作者日常学习笔记,请勿利用文章内的相关技术从事非法测试,如因此产生的一切不良后果与作者无关。 目录 一、漏洞描述 二、影响版本 三、资产测绘 四、漏洞复现

【css】css实现文字两端对齐效果:

文章目录 一、方法1&#xff1a;二、方法2&#xff1a;三、注意&#xff1a; 一、方法1&#xff1a; 给元素设置 text-align: justify;text-align-last: justify;并且加上text-justify: distribute-all-line; 目的是兼容ie浏览器 p{width: 130px;text-align: justify;text-alig…

飞天使-linux操作的一些技巧与知识点3-http的工作原理

文章目录 http工作原理nginx的正向代理和反向代理的区别一个小技巧dig 命令巧用 http工作原理 http1.0 协议 使用的是短连接&#xff0c;建立一次tcp连接&#xff0c;发起一次http的请求&#xff0c;结束&#xff0c;tcp断开 http1.1 协议使用的是长连接&#xff0c;建立一次tc…

Network 灰鸽宝典【目录】

目前已有文章 21 篇 Network 灰鸽宝典专栏主要关注服务器的配置&#xff0c;前后端开发环境的配置&#xff0c;编辑器的配置&#xff0c;网络服务的配置&#xff0c;网络命令的应用与配置&#xff0c;windows常见问题的解决等。 文章目录 服务配置环境部署GitNPM 浏览器编辑器系…

GEE:重分类

作者:CSDN @ _养乐多_ 本文记录了在 Google Earth Engine(GEE)平台上对一副类别图像进行重分类的代码。并以 COPERNICUS/Landcover/100m/Proba-V-C3/Global 数据集中的土地利用数据为例。 结果如下图所示, 文章目录 一、核心函数二、示例代码三、代码链接一、核心函数 核…

文件操作及函数

什么是文件&#xff1f; 在程序设计中&#xff0c;文件有两种&#xff1a;程序文件和数据文件。 程序文件 包括源程序文件&#xff08;.c&#xff09;&#xff0c;目标文件&#xff08;.obj&#xff09;&#xff0c;可执行程序(.exe)。 数据文件 文件的内容不一定是程序&…

linux下部署frp客户端服务端-内网穿透

简介 部署在公司内部局域网虚拟机上的服务需要在外网能够访问到&#xff0c;这不就是内网穿透的需求吗&#xff0c;之前通过路由器实现过&#xff0c;现在公司这块路由器不具备这个功能了&#xff0c;目前市面上一些主流的内网穿透工具有&#xff1a;Ngrok&#xff0c;Natapp&…