当前位置: 首页 > ai >正文

Protobuf

Protobuf

Protobuf 是什么

ProtoBuf(全称 Protocol Buffer)是数据结构序列化和反序列化框架,它具有以下特点:

• **语言无关、平台无关:**即 ProtoBuf 支持 Java、C++、Python 等多种语言,支持多个平台

• **高效:**即比 XML 更小、更快、更为简单

• **扩展性、兼容性好:**你可以更新数据结构,而不影响和破坏原有的旧程序

Protobuf 使用流程介绍

在这里插入图片描述

• 编写 .proto 文件,目的是为了定义结构对象(message)及属性内容

• 使用 protoc 编译器编译 .proto 文件,生成一系列接口代码,存放在新生成头文件和源文件中

• 依赖生成的接口,将编译生成的头文件包含进我们的代码中,实现对 .proto 文件中定义的字段进行设置和获取,和对 message 对象进行序列化和反序列化

ProtoBuf 快速上手

我们以一个简单通讯录的实现来驱动对 Protobuf 的学习。在通讯录 demo 中,我们将

实现:

• 对一个联系人的信息使用 Protobuf 进行序列化,并将结果打印出来

• 对序列化后的内容使用 Protobuf 进行反序列,解析出联系人信息并打印出来

• 联系人包含以下信息: 姓名、年龄

通过通讯录 demo,我们能快速的了解 ProtoBuf 的使用流程。

创建 .proto 文件

.proto 文件规范

• 创建 .proto 文件时,文件命名应该使用全小写字母命名,多个字母之间用 _ 连接。

例如:lower_snake_case.proto

• 书写 .proto 文件代码时,应使用 2 个空格的缩进我们为通讯录 demo 新建文件: contacts.proto

添加注释向文件添加注释,可使用// 或者 /* … */

指定 proto3 语法

Protocol Buffers 语言版本 3,简称 proto3,是 .proto 文件最新的语法版本。proto3 简化了 Protocol Buffers 语言,既易于使用,又可以在更广泛的编程语言中使用。它允许你使用 Java,C++,Python 等多种语言生成 protocol buffer 代码。在 .proto 文件中,要使用 syntax = “proto3”; 来指定文件语法为 proto3,并且必须写在除去注释内容的第一行。 如果没有指定,编译器会使用 proto2 语法。

在通讯录 demo 的 contacts.proto 文件中,可以为文件指定 proto3 语法,内容如下:

syntax = "proto3";

package 声明符

package 是一个可选的声明符,能表示 .proto 文件的命名空间,在项目中要有唯一性。

它的作用是为了避免我们定义的消息出现冲突。

在通讯录 demo 的 contacts.proto 文件中,可以声明其命名空间,内容如下:

syntax = "proto3";
package contacts;

定义消息(message)

消息(message): 要定义的结构化对象,我们可以给这个结构化对象中定义其对应的属性内容。在网络传输中,我们需要为传输双方定制协议。定制协议说白了就是定义结构体或者结构化数据,比如,tcp,udp 报文就是结构化的。再比如将数据持久化存储到数据库时,会将一系列元数据统一用对象组织起来,再进行存储。ProtoBuf 就是以 message 的方式来支持我们定制协议字段,后期帮助我们形成类和方法来使用。

在通讯录 demo 中我们就需要为 联系人 定义一个 message:

• .proto 文件中定义一个消息类型的格式为:

message 消息类型名{ 
} 
消息类型命名规范:使用驼峰命名法,首字母大写。

为 contacts.proto(通讯录 demo)新增联系人 message

syntax = "proto3";
package contacts;
// 定义联系人消息
message PeopleInfo {
}

定义消息字段

在 message 中我们可以定义其属性字段,字段定义格式为:字段类型 字段名 = 字段唯一编号;

• 字段名称命名规范:全小写字母,多个字母之间用 _ 连接。

• 字段类型分为:标量数据类型 和 特殊类型(包括枚举、其他消息类型等)。

• 字段唯一编号:用来标识字段,一旦开始使用就不能够再改变。

该表格展示了定义于消息体中的标量数据类型,以及编译 .proto 文件之后自动生成的类中与之对应的字段类型。

更新 contacts.proto, 新增姓名、年龄字段:

syntax = "proto3";
package contacts;
message PeopleInfo {string name = 1; int32 age = 2; 
}

注:这里还要特别讲解一下字段唯一编号的范围:

1 ~ 536,870,911 (2^29 - 1) ,其中 19000 ~ 19999 不可用。

19000 ~ 19999 不可用是因为:在 Protobuf 协议的实现中,对这些数进行了预留。如果非要在.proto 文件中使用这些预留标识号,例如将 name 字段的编号设置为 19000,编译时就会报警:

// 消息中定义了如下编号,代码会告警:
// Field numbers 19,000 through 19,999 are reserved for the 
protobuf implementation
string name = 19000;

值得一提的是,范围为 1 ~ 15 的字段编号需要一个字节进行编码, 16 ~ 2047 内的数字需要两个字节进行编码。编码后的字节不仅只包含了编号,还包含了字段类型。所以 1 ~ 15 要用来标记出现非常频繁的字段,要为将来有可能添加的、频繁出现的字段预留一些出来

编译 contacts.proto 文件

编译命令行格式为:

protoc [--proto_path=IMPORT_PATH] --cpp_out=DST_DIR 
path/to/file.proto
protoc 是 Protocol Buffer 提供的命令行编译工具。
--proto_path 指定 被编译的.proto 文件所在目录,可多次指定。可
简写成 -I IMPORT_PATH 。如不指定该参数,则在当前目录进行搜索。当某个.proto 文件
import 其他 .proto 文件时,或需要编译的 .proto 文件不在当前目录下,这时就要
用-I 来指定搜索目录。
--cpp_out= 指编译后的文件为 C++ 文件。
OUT_DIR 编译后生成文件的目标路径。
path/to/file.proto 要编译的.proto 文件。

编译 contacts.proto 文件命令如下:

protoc --cpp_out=. contacts.proto

编译 contacts.proto 文件后,会生成所选择语言的代码,我们选择的是 C++,所以编译后生成了两个文件:contacts.pb.h contacts.pb.cc。

对于编译生成的 C++ 代码,包含了以下内容 :

• 对于每个 message ,都会生成一个对应的消息类

• 在消息类中,编译器为每个字段提供了获取和设置方法,以及一下其他能够操作字段的方法

的代码,我们选择的是 C++,所以编译后生成了两个文件:contacts.pb.h contacts.pb.cc。

对于编译生成的 C++ 代码,包含了以下内容 :

• 对于每个 message ,都会生成一个对应的消息类

• 在消息类中,编译器为每个字段提供了获取和设置方法,以及一下其他能够操作字段的方法

• 编辑器会针对于每个 .proto 文件生成.h 和 .cc 文件,分别用来存放类的声明与类的实现

http://www.xdnf.cn/news/20292.html

相关文章:

  • 人工智能辅助荧光浓度检测系统:基于YOLO与RGB分析的Python实现
  • 【序列晋升】29 Spring Cloud Task 微服务架构下的轻量级任务调度框架
  • AP1272:新一代高性能LDO稳压器,为精密电子系统提供更优电源解决方案
  • 《秦时明月》系列经典语录分享
  • 云原生的12个要素是什么?
  • 【Linux指南】动静态库与链接机制:从原理到实践
  • 疯狂星期四文案网第62天运营日记
  • 消失的6个月!
  • 从文本到知识:使用LLM图转换器构建知识图谱的详细指南
  • Java多线程学习笔记
  • Nginx 实战系列(二)—— Nginx 配置文件与虚拟主机搭建
  • QML Charts组件之LineSeries、SplineSeries与ScatterSeries
  • 正态分布 - 正态分布的经验法则(68-95-99.7 法则)
  • Modbus通信的大端和小端字节序
  • OpsManage 项目启动脚本与 Docker 配置深度分析
  • Day05 单调栈 | 84. 柱状图中最大的矩形、42. 接雨水
  • LeetCode算法日记 - Day 34: 二进制求和、字符串相乘
  • 【目录-多选】鸿蒙HarmonyOS开发者基础
  • 分布式go项目-搭建监控和追踪方案
  • 国内外支持个人开发者的应用市场
  • OpenCV - 图像的IO操作
  • 【开题答辩全过程】以 住院管理系统为例,包含答辩的问题和答案
  • 从零开始的python学习——文件
  • C++ 面向对象编程:多态相关面试简答题
  • 444444
  • LeetCode - 1089. 复写零
  • MQTT 与 Java 框架集成:Spring Boot 实战(三)
  • RAG提示词分解
  • CentOS系统管理:useradd命令的全面解析
  • Vllm-0.10.1:通过vllm bench serve测试TTFT、TPOT、ITL、E2EL四个指标