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,一经查实,立即删除!

相关文章

MAC IDEA Maven Springboot

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

【二分查找】【双指针】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. 空间决策…

基于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,而在执行语句部分…

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

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

【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&…

Docker镜像构建:深入Dockerfile创建自定义镜像

Docker的强大之处在于其能够通过Dockerfile定义和构建自定义镜像&#xff0c;为应用提供独立、可移植的运行环境。在这篇博客文章中&#xff0c;将深入探讨Docker镜像构建的核心概念&#xff0c;通过更加丰富的示例代码&#xff0c;帮助大家全面理解和掌握构建自定义镜像的技术…

深度学习在人体动作识别领域的应用:开源工具、数据集资源及趋动云GPU算力不可或缺

人体动作识别检测是一种通过使用计算机视觉和深度学习技术&#xff0c;对人体姿态和动作进行实时监测和分析的技术。该技术旨在从图像或视频中提取有关人体姿态、动作和行为的信息&#xff0c;以便更深入地识别和理解人的活动。 人体动作识别检测的基本步骤包括&#xff1a; 数…

关于MySQL的bigint问题

MySQL的bigint(8)能存多大数值&#xff1f; MySQL的BIGINT(8)可以存储的数值范围是从-9,223,372,036,854,775,808到9,223,372,036,854,775,807。这是因为BIGINT数据类型在MySQL中使用8字节进行存储&#xff0c;每个字节有8位&#xff0c;所以总共可以表示2^64个不同的整数。 …

IDEA 出现问题:git提交commit时Perform code analysis卡住解决方案

问题 git提交commit时Perform code analysis卡住很久 解决方案一 1、打开 IntelliJ IDEA&#xff0c;进入 File -> Settings&#xff08;或者使用快捷键 CtrlAltS&#xff09;。 2、在弹出的 Settings 窗口中&#xff0c;找到 Version Control -> Commit Dialog 选项…

什么是数字化营销?如何进行数字化营销?数字化有多重要?

引言 数字化营销是一种利用数字技术和在线平台来促进产品或服务销售的策略。它包括利用各种数字渠道&#xff0c;如社交媒体、搜索引擎优化、内容营销和数据分析等&#xff0c;与目标受众建立联系并推动销售。 在当今商业环境中&#xff0c;数字化营销扮演着至关重要的角色。…

阿里云国际版无法远程连接Windows服务器的排查方法

如果您遇到紧急情况&#xff0c;需要尽快登录Windows实例&#xff0c;请参见以下操作步骤&#xff0c;先检查ECS实例的状态&#xff0c;然后通过云助手向Windows实例发送命令或通过VNC登录实例&#xff0c;具体步骤如下&#xff1a; 步骤一&#xff1a;检查ECS实例状态 无论何…

SpringBoot之请求的详细解析

1. 请求 在本章节呢&#xff0c;我们主要讲解&#xff0c;如何接收页面传递过来的请求数据。 1.1 Postman 之前我们课程中有提到当前最为主流的开发模式&#xff1a;前后端分离 在这种模式下&#xff0c;前端技术人员基于"接口文档"&#xff0c;开发前端程序&…

智能优化算法应用:基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于萤火虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.萤火虫算法4.实验参数设定5.算法结果6.参考文…