rpc中常用的数据格式:Protobuf 图文详解

devtools/2024/10/19 13:18:40/

概述

protobuf也叫protocol buffer,是google 的一种数据交换的格式,它跨语言、跨平台。可以实现多种语言文件的数据传输实现(java、c#、c++、go 和 python 等),如一个cpp程序和一个python程序的数据传输。

由于它是一种二进制的格式,比使用 xml 、json进行数据交换快许多。所以它的效率和兼容性都很优秀,可以把它用于分布式应用之间的数据通信。

编译与安装

通过百度网盘分享的文件:proto
链接:https://pan.baidu.com/s/1o7Vmcyofz6r_phLdh-A2lA?pwd=t172 
提取码:t172

解压后运行shell脚本即可

编写简单的proto文件

proto文件

// 声明protobuf的版本
syntax = "proto3";
// 声明代码所在的包, 相当他cpp的namespace
package fixbug;// 定义下面选项, 才可以生成service服务类和rpc方法描述, 默认不生成
option cc_generic_services = true;message ResultCode {int32 errcode = 1;bytes errmsg = 2;bool success = 3;
}// 定义登录消息类型(结构体)
message LoginRequest {// 1 表示数据的序号bytes name = 1; // bytes = stringbytes pwd = 2;
}// 定义登录响应消息类型
message LoginResponse {ResultCode result = 1;bool success = 2;
}message GetFriendListsRequest { uint32 userid = 1; }message User {bytes name = 1;uint32 age = 2;enum Sex {MAN = 0;WOMAN = 1;}Sex sex = 3;
}message GetFriendListsResponse {ResultCode result = 1;bool success = 2;// 存储列表repeated User friend_list = 3;
}// 在protobuf里面定义描述rpc方法的类型 -service
service UserServiceRpc {rpc Login(LoginRequest) returns (LoginResponse);rpc GetFriendList(GetFriendListsRequest) returns (GetFriendListsResponse);
}

在终端中执行

protoc test.proto --cpp_out=./

test.proto是你自定义的proto文件

然后会得到test.pb.h、test.pb.cc文件

proto自定义数据结构与.pb.h中函数的关系

test.pb.h初看有些复杂,但其实都是有规律的

image-20241012201312528

1.常规变量类型

这里的常规变量,指的是string、int等类型,而不是自定义的数据结构

// 定义登录消息类型(结构体)
message LoginRequest {// 1 表示数据的序号bytes name = 1; // bytes = stringbytes pwd = 2;
}

转为pb.cc文件后,主要分为两种读写函数:

  • set_变量名():如set_name(),往name变量中写数据
  • 变量名():如name(),只读访问name变量

2.自定义变量类型

message GetFriendListsResponse {ResultCode result = 1;bool success = 2;// 存储列表repeated User friend_list = 3;
}

转为 pb.cc 文件后,主要分为两种读写函数:

  • mutable_变量名():如ResultCode* mutable_result(),获得变量result的指针,之后就可读可写了
  • 变量名():如name(),只读访问name变量

注意对于 repeated User friend_list 变量,还会有:

使用 repeated 关键字定义的字段在 Protobuf 序列化和反序列化时会被当作一个集合或数组来处理。这个 User friend_list 可以作为一个动态数组来使用。

  • add_变量名():如 User* add_friend_list(),它返回的是要新增元素地址

3.service服务

在proto中我们会定义远程调用的服务函数

service UserServiceRpc {rpc Login(LoginRequest) returns (LoginResponse);rpc GetFriendList(GetFriendListsRequest) returns (GetFriendListsResponse);
}
  • 转为pb.cc文件后,会从 ”结构体“名 (这里是 UserServiceRpc)继承,得到 ”结构体“名_Stub 这个类(这里是UserServiceRpc_Stub
  • UserServiceRpc_Stub 的构造函数是由一个 RpcChannel* channel 作为参数的传入的
  • 而 proto 文件中定义的 LoginGetFriendList 函数,本质上是调用 CallMethod 函数(channel_->CallMethod(descriptor()->method(0),controller, request, response, done);
  • 再追溯一下,RpcChannel 是一个类,里面是 CallMethod 函数是虚函数,这说明 RpcChannel 类以及它的 CallMethod 函数,都需要我们开发者进行重写

序列化与反序列化

  • 序列化是将数据结构或对象转换为可以存储或传输的格式(通常是字节序列/string类型)的过程。

    其目的是将复杂的数据结构转化为一种便于存储、传输或在不同系统之间交换的形式。

  • 反序列化则是序列化的逆过程,它将序列化后的数据(如字节流)重新转换回原始的数据结构或对象。

    假设我们有一个包含学生姓名、年龄和成绩的对象。序列化可能会将这个对象转换为一个特定格式的字符串,如 {“name”:“张三”,“age”:20,“score”:90} 。而反序列化就是把接收到的这样的字符串重新转换回包含姓名、年龄和成绩的学生对象。

image-20241012204439211

【protobuf】ProtoBuf——序列化概念、序列化和反序列化、为什么需要序列化和反序列化、如何实现序列化、ProtoBuf 是什么、ProtoBuf 的使用特点-CSDN博客

#include "test.pb.h"
#include <iostream>
#include <string>
using namespace fixbug;int main()
{// 初始化变量, 封装了login请求对象的数据LoginRequest req;req.set_name("zhang san");req.set_pwd("123456");// 对象数据序列化, => stringstd::string send_str;if(req.SerializeToString(&send_str)){std::cout << send_str << std::endl;}// 从send_str中反序列化一个login请求对象LoginRequest reqB;if(reqB.ParseFromString(send_str)){std::cout << reqB.name() << std::endl;std::cout << reqB.pwd() << std::endl;}return 0;
}

http://www.ppmy.cn/devtools/125077.html

相关文章

idea - properties文件unicode中文显示

&#x1f496;简介 idea中properties文件中文默认展示为unicode码 unicode 中文展示为 \u开头的ASCII &#x1f31f;调整中文显示 idea -> settings -> Editor -> File Encodings Global Encoding 选择 UTF-8 Project Encoding 选择 UTF-8 Default encoding for pro…

如何设计一个低成本数据归档及查询的架构

引言 随着企业数据的快速增长&#xff0c;如何高效地管理和查询这些数据成为了一个亟待解决的问题。尤其是当数据量达到一定程度时&#xff0c;传统的数据存储和查询方式往往面临成本高、效率低等挑战。因此&#xff0c;设计一个低成本、高效的数据归档及查询架构变得尤为重要…

系统架构设计师⑧:软件工程-需求工程

系统架构设计师⑧&#xff1a;软件工程-需求工程 软件需求的定义 软件需求是指用户对系统在功能、行为、性能、设计约束等方面的期望。 需求获取 需求分析-SA 需求分析-E-R图 需求分析-面向对象-相关概念 面向对象建模 UML&#xff08;统一建模语言&#xff09; UML图 UML-…

系统思考与业务创新工作坊

圆满结束两天的新华三《系统思考与业务创新工作坊》项目&#xff01;在这次工作坊中&#xff0c;我们不仅深入探讨了如何通过系统思维看清复杂的业务全貌&#xff0c;还一起探索了创新背后的逻辑与突破口。 系统思考不是一时的灵感&#xff0c;而是一种持久的思维模式&#xff…

目标检测——YOLO11算法解读

作者&#xff1a;Ultralytics公司 代码&#xff1a;https://github.com/ultralytics/ultralytics YOLO系列算法解读&#xff1a; YOLOv1通俗易懂版解读、SSD算法解读、YOLOv2算法解读、YOLOv3算法解读、YOLOv4算法解读、YOLOv5算法解读、YOLOR算法解读、YOLOX算法解读、YOLOv6算…

Maven打包运行,引入三方jar及打包,不导入本地库的方法

Maven打包运行&#xff0c;引入三方jar及打包&#xff0c;不导入本地库的方法 maven、打包、springboot、jar、本地、引入背景 业务系统要对接某硬件&#xff0c;需要用到其三方jar&#xff0c;maven官方仓库没有这个&#xff0c;我也没有maven&#xff0c;又不想mvn install…

5G NR物理信号

文章目录 NR 物理信号与LTE的区别上行参考信号DMRS (UL)SRSPT-RS(UL) 下行参考信号DMRS(DL)PT-RS(DL)CSI-RSPSSSSS NR 物理信号与LTE的区别 用SSS、CSI-RS和DMRS 取代了CRS信号。下行业务信道采用TM1波束赋形传输模式。基于SSB 或者CSI-RS进行RSRP和SINR测量。基于DMRS 进行共…

图像分类-demo(Lenet),tensorflow和Alexnet

目录 demo(Lenet) 代码实现基本步骤&#xff1a; TensorFlow 一、核心概念 二、主要特点 三、简单实现 参数: 模型编译 模型训练 模型评估 Alexnet model.py train.py predict.py demo(Lenet) PyTorch提供了一个名为“torchvision”的附加库&#xff0c;其中包含…