protobuf 讲解

news2024/10/4 10:08:36

一、序列化概念回顾

二、什么是PB

将结构化数据进行序列化的一种方式

三、PB的特点

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

高效:即比XML更小,更快,更为简单。

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

使用特点:ProtoBuf是需要依赖通过编译生成的头文件和源文件来使用。

四、安装ProtoBuf

ProtoBuf下载地址:https://github.com/protocolbuffers/protobuf/releases

1、在windows安装

配置一下环境变量就可以了

protoc --version 打印出版本

2、在ubuntu下安装

下载依赖器

下载protoBuf

解压包 unzip

编译生成protobuf

一次执行下面的命令 大概需要半个小时左右

这里需要更改profile,修改环境变量

sudo vim /etc/profile

在里面添加下面的内容

#(动态库搜索路径) 程序加载运⾏期间查找动态链接库时指定除了系统默认路径之外的其他路径export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/protobuf/lib/
#(静态库搜索路径) 程序编译期间查找动态链接库时指定查找共享库的路径
export LIBRARY_PATH=$LIBRARY_PATH:/usr/local/protobuf/lib/
#执⾏程序搜索路径
export PATH=$PATH:/usr/local/protobuf/bin/
#c程序头⽂件搜索路径
export C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/local/protobuf/include/
#c++程序头⽂件搜索路径
export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/local/protobuf/include/
#pkg-config 路径
export PKG_CONFIG_PATH=/usr/local/protobuf/lib/pkgconfig/

再执行这个命令:

source /etc/profile

另外需要说一下Centos用户在安装的时候需要用到这个命令

sudo yum install autoconf automake libtool curl make gcc-c++ unzip

五、使用ProtoBuf

使用protobuf,实现一个通讯录项目,一个版本一个版本的实现,从而有效推进protobuf的学习。

快速上手

目的:完整使用PB,学习基本语法。

在快速上手中,我们会编写第一个版本的通讯录1.0。

• 对⼀个联系⼈的信息使⽤PB进⾏序列化,并将结果打印出来。

• 对序列化后的内容使⽤PB进⾏反序列,解析出联系⼈信息并打印出来。

• 联系⼈包含以下信息:姓名、年龄。
通过通讯录1.0,我们便能了解使⽤ProtoBuf初步要掌握的内容,以及体验到ProtoBuf的完整使⽤流程。

步骤一:创建.protobuf

步骤二:进行编译

-I 指定搜索目录

步骤三:

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

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

六、proto3语法详解

升级版本的通讯录

• 不再打印联系⼈的序列化结果,⽽是将通讯录序列化后并写⼊⽂件中。

• 从⽂件中将通讯录解析出来,并进⾏打印。
• 新增联系⼈属性,共包括:姓名、年龄、电话信息、地址、其他联系⽅式、备注。

1、字段规则、消息类型的定义和使用

新增联系人的属性。

repeated来定义一个数组。消息中可以包含该字段任意多次(包括零次),其中重复值的顺序会被保留。可以理解为定义了⼀个数组。

singular的规则,消息中可以包含该字段零次或⼀次(不超过⼀次)。proto3语法中,字段默认使⽤该规则。

可以嵌套定义message。

引入 phone文件

定义通讯录proto文件

把通讯录的信息写入文件,首先编写makefile文件。

里面调用的函数返回的是一个已经开辟好的空间所以我们可以使用这个空间直接对contact新增联系人。

查看二进制文件

读取文件

decode的使用

2、proto3语法理解enum类型

0必须存在,必须在第一个。

也可以定义在消息体内

不能让同级的enum类型中的成员系统,多个文件中的enum类型中的类型也不能同名。会编译报错。解决方法:可以包含一个命名空间进行隔离。

通讯录2.1,更新proto文件

设置联系人电话类型

修改打印函数

枚举类型会被默认设置。反序列化时会设置枚举值为0的枚举类型。

3、Any类型的讲解

Any类型可以被理解为是一个泛型类型。可以存储任意的消息类型。

通讯录2.2版本 使用Any字段存放联系人地址。

新增联系人地址

读出联系人地址

4、oneof类型讲解

2.3版本新增其他联系方式

只能设置一个其他联系方式

字段编号不能重复,不能使用repeated来修饰里面的值,

添加联系人的其他联系方式

读取联系人的其他联系方式

5、map类型的使用

2.4版本,增加备注

不能使用repeated来修饰,设置的kv值是无序的

设置联系人备注信息

打印备注信息

6、默认值讲解

反序列化消息时,如果被反序列化的⼆进制序列中不包含某个字段,反序列化对象中相应字段时,就会设置为该字段的默认值。不同的类型对应的默认值不同:

• 对于字符串,默认值为空字符串。
• 对于字节,默认值为空字节。
• 对于布尔值,默认值为false。
• 对于数值类型,默认值为0。
• 对于枚举,默认值是第⼀个定义的枚举值,必须为0。

• 对于消息字段,未设置该字段。它的取值是依赖于语⾔。• 对于设置了repeated的字段的默认值是空的(通常是相应语⾔的⼀个空列表)。

• 对于 消息字段 、 oneof字段 和 any字段 ,C++和Java语⾔中都有has_⽅法来检测当前字段是否被设置。

对于标量数据类型,在proto3语法下,没有生成has_方法。不确定是用户设置的还是一个默认值。

7、更新消息

新增字段

注意不要和老字段冲突即可

修改字段

• 禁⽌修改任何已有字段的字段编号。

• 若是移除⽼字段,要保证不再使⽤移除字段的字段编号。正确的做法是保留字段编号
(reserved),以确保该编号将不能被重复使⽤。不建议直接删除或注释掉字段。

• int32,uint32,int64,uint64和bool是完全兼容的。可以从这些类型中的⼀个改为另⼀个,
⽽不破坏前后兼容性。若解析出来的数值与相应的类型不匹配,会采⽤与C++⼀致的处理⽅案(例如,若将64位整数当做32位进⾏读取,它将被截断为32位)。
• sint32和sint64相互兼容但不与其他的整型兼容。• string和bytes在合法UTF-8字节前提下也是兼容的。

• bytes包含消息编码版本的情况下,嵌套消息与bytes也是兼容的。

• fixed32与sfixed32兼容,fixed64与sfixed64兼容。
• enum与int32,uint32,int64和uint64兼容(注意若值不匹配会被截断)。但要注意当反序
列化消息时会根据语⾔采⽤不同的处理⽅案:例如,未识别的proto3枚举类型会被保存在消息中,但是当消息反序列化时如何表⽰是依赖于编程语⾔的。整型字段总是会保持其的值。
• oneof:

◦ 将⼀个单独的值更改为新oneof类型成员之⼀是安全和⼆进制兼容的。

◦ 若确定没有代码⼀次性设置多个值那么将多个字段移⼊⼀个新oneof类型也是可⾏的。

◦ 将任何字段移⼊已存在的oneof类型是不安全的。

删除字段

不能直接删除已存在的字段,

如果要删除老子段,要保证不使用已经被删除的或者已经被注释掉的字段编号,会导致下列问题

如何不使用已经被注释掉的字段编号呢?

reserved保留项

指定保留的字段编号

会有一个错误发生

还可以这样写

结果:我们看到年龄不在使用前面的字段编号了

上面的生日信息哪里去了呢。被存放到了未知字段中。

未知字段

未知字段是什么?

• 未知字段:解析结构良好的protocolbuffer已序列化数据中的未识别字段的表⽰⽅式。例如,当旧程序解析带有新字段的数据时,这些新字段就会成为旧程序的未知字段。
• 本来,proto3在解析消息时总是会丢弃未知字段,但在3.5版本中重新引⼊了对未知字段的保留机制。所以在3.5或更⾼版本中,未知字段在反序列化时会被保留,同时也会包含在序列化的结果中。

从哪获取未知字段?

通过Reflection类中UnKnowFields()方法获取

打印未知字段

前后兼容性

向前兼容:⽼模块能够正确识别新模块⽣成或发出的协议。这时新增加的“⽣⽇”属性会被当作未 知字段(pb 3.5版本及之后)。
向后兼容:新模块也能够正确识别⽼模块⽣成或发出的协议。
前后兼容的作⽤:当我们维护⼀个很庞⼤的分布式系统时,由于你⽆法同时 升级所有 模块,为了保证 在升级过程中,整个系统能够尽可能不受影响,就需要尽量保证通讯协议的“向后兼容”或“向前兼容”。

8、option选项语法详解

option选项可以影响ProtoBuf的编译属性。用的不太多,所以我们可以用文档看一下就可以了。

七、通讯录4.0实现 --- 网络版

服务器

客户端

客户端调用接口req,调用返回resp。

客户端的.proto文件和服务器的相同

客户端的菜单编写

服务端书写 add del findALL findOne接口。每个接口会有req,resp协议。

序列化req

调用接口

反序列化req 新增一个联系人,持久化存储通讯录

序列化resp

反序列化resp

AddContact方法

protobuf远远比json的序列化和反序列化效率高。json的内存占用比protobuf多一倍。

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

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

相关文章

MATLAB使用眼图分析QPSK通信系统接收端匹配滤波后的信号

文章目录 前言一、MATLAB仿真代码二、仿真结果 前言 本文完成以下内容: (1)建立一个QPSK传输系统,并引入EsNo20dB(SNR0dB)的噪声,接收端对带噪信号进行匹配滤波。 (2)分…

Python并发编程挑战与解决方案

Python并发编程挑战与解决方案 并发编程是现代软件开发中的一项核心能力,它允许多个任务同时运行,提高程序的性能和响应速度。Python因其易用性和灵活性而广受欢迎,但其全局解释器锁(GIL)以及其他特性给并发编程带来了…

CSS实现服务卡片

CSS实现服务卡片 效果展示 CSS 知识点 回顾整体CSS知识点灵活运用CSS知识点 页面整体布局 <div class"container"><div class"card"><div class"box"><div class"icon"><ion-icon name"color-pal…

python集合set

1、集合是无序的&#xff0c;所以集合不支持下标访问索引 2、集合的常见操作 3、集合内不允许重复元素 4、注意

若依cloud升级mybaits-plus方法

1、在主pom文件中引入依赖 <!-- mybatis-plus 增强CRUD --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency> 2、在ruoyi-comm…

基于大数据的Python+Django电影票房数据可视化分析系统设计与实现

目录 1 引言 2 系统需求分析 3 技术选型 4 系统架构设计 5 关键技术实现 6 系统实现 7 总结与展望 1 引言 随着数字媒体技术的发展&#xff0c;电影产业已经成为全球经济文化不可或缺的一部分。电影不仅是艺术表达的形式&#xff0c;更是大众娱乐的重要来源。在这个背景…

Java 每日一刊(第20期):I/O 流

文章目录 前言流的起源及概念Java I/O 流概述字节流字符流转换流缓冲流对象流与序列化NIO&#xff08;New I/O&#xff09;流的关闭与资源管理本期小知识 前言 这里是分享 Java 相关内容的专刊&#xff0c;每日一更。 本期将为大家带来以下内容&#xff1a; 流的起源及概念J…

各省-城镇化率(2001-2022年)

数据收集各省-城镇化率&#xff08;2001-2022年&#xff09;.zip资源-CSDN文库https://download.csdn.net/download/2401_84585615/89465885 相关指标&#xff1a; 包括省份、年份、年末总人口数(万人)、年末城镇人口数(万人)、城镇化率等。 数据集构建&#xff1a; 数据集通…

(7)MATLAB:QPSK理论误符号率和理论误比特率

文章目录 前言一、QPSK系统的平均误码率二、QPSK系统的平均误比特率1.根据误码率计算从QPSK符号&#xff08;四进制&#xff09;译为比特串的比特错误率。2.使用最佳接收的误比特率计算公式。 三、MATLAB代码实现与结果1.代码实现2.性能曲线画图 总结参考资料 前言 本文给出QP…

YOLOv8改进,YOLOv8改进主干网络为GhostNetV2(华为的轻量化架构)

摘要 摘要:轻量级卷积神经网络(CNN)专为移动设备上的应用而设计,具有更快的推理速度。卷积操作只能在窗口区域内捕捉局部信息,这限制了性能的进一步提升。将自注意力引入卷积可以很好地捕捉全局信息,但会极大地拖累实际速度。本文提出了一种硬件友好的注意力机制(称为 D…

[深度学习][python]yolov11+deepsort+pyqt5实现目标追踪

【算法介绍】 YOLOv11、DeepSORT和PyQt5的组合为实现高效目标追踪提供了一个强大的解决方案。 YOLOv11是YOLO系列的最新版本&#xff0c;它在保持高检测速度的同时&#xff0c;通过改进网络结构、优化损失函数等方式&#xff0c;提高了检测精度&#xff0c;能够同时处理多个尺…

系统架构设计师④:计算机网络

系统架构设计师④&#xff1a;计算机网络 TCP/IP协议族 模型如下&#xff1a; 常用的协议及端口号&#xff1a; 各个协议能力介绍&#xff1a; TCP与UDP的对比&#xff1a; DNS协议 DSN&#xff1a;域名系统( Domain Name System) 支持两种查询方式 &#xff1a; ①递…

MATLAB中qmr函数用法

目录 语法 说明 示例 线性系统的迭代解 使用指定了预条件子的 qmr 提供初始估计值 使用函数句柄代替数值矩阵 qmr函数的功能是求解线性系统 - 拟最小残差法。 语法 x qmr(A,b) x qmr(A,b,tol) x qmr(A,b,tol,maxit) x qmr(A,b,tol,maxit,M) x qmr(A,b,tol,maxit,…

蓝桥杯【物联网】零基础到国奖之路:十八. 扩展模块之光敏和AS312

蓝桥杯【物联网】零基础到国奖之路:十八.扩展模块之光敏和AS312 第一节 硬件解读第二节 CubeMX配置第二节 代码 第一节 硬件解读 光敏和AS312如下图&#xff1a; 光敏电阻接到了扩展模块的5号引脚&#xff0c;5号引脚接了2个电阻&#xff0c;R8和光敏电阻。我们通过ADC读取这…

RNN:我们一直忽略的宝藏?揭开递归神经网络的真正潜力

说到AI,我们第一个想到的可能是ChatGPT、Transformer这些大名鼎鼎的技术。但你有没有想过,其实我们“遗忘”的RNN(递归神经网络)可能才是真正的宝藏?最近有一篇论文提到一个耐人寻味的问题:“RNN真的是我们唯一需要的技术吗?” 这个问题不仅让我陷入深思,也引发了对RNN…

SpringSession;基于Redis的SpringSession实现;实现session共享的三种方式

一&#xff0c;SpringSession简介 是SpringCloud下管理session的框架&#xff0c;在微服务架构中&#xff0c;由于应用了分布式的思想&#xff0c;session无法做到内存中互通&#xff0c;需要一个框架来实现各个微服务中session数据共享&#xff0c;SpringSession解决了这个问题…

Unity 3D 游戏发布一口气讲完!(o-ωq)).oO 困

Unity 3D PC平台发布 PC 是最常见的游戏运行平台。 随着欧美游戏的崛起&#xff0c;PC 平台随之发生游戏登陆大潮。 在 PC 平台上发布游戏的步骤&#xff1a; 打开要发布的 Unity 3D 工程&#xff0c;执行 File → Build Settings 菜单命令。 在 Platform 列表框中选择 PC&a…

返回索引对象中各元素的数据类型 pandas.Index.dtype

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 返回索引对象中 各元素的数据类型 pandas.Index.dtype [太阳]选择题 根据题目代码&#xff0c;执行idx3.dtype的结果是&#xff1f; import pandas as pd idx1 pd.Index([1, 2, 3, 4, 5])…

C++网络编程之TCP协议

概述 TCP&#xff0c;即传输控制协议&#xff0c;英文全称为Transmission Control Protocol&#xff0c;是互联网协议套件中的核心协议之一。它工作在OSI七层模型的传输层&#xff0c;也工作在TCP/IP四层模型的传输层。TCP协议的主要目的是&#xff1a;在不可靠的网络环境中提供…

基础算法--枚举

枚举算法是一种简单而有效的算法&#xff0c;它通过枚举所有可能的情况来解决问题。它通常用于解决问题规模比较小的问题&#xff0c;因为它的时间复杂度很高&#xff0c;随着问题的规模增加&#xff0c;算法的效率会急剧下降。 枚举算法的基本思路是通过循环遍历所有可能的情…