Protobuf:基本概念与使用流程

Protobuf:基本概念与使用流程

    • 基本概念
    • Linux 安装
    • 使用流程
      • .proto文件
      • 编译
      • 使用
    • 运行机制


基本概念

在进行网络编程时,经常需要进行数据传输,只有双方主机都保证数据格式的一致性,才能保证数据被正常解析。这个过程称为序列化反序列化,当前主流的标准有jsonxml等,而protobuf就是其中一个数据格式的标准。

jsonxml都是人类可视化的序列化形式,存储的都是字符串,哪怕没有程序解析都可以直接读取。

比如一个Person类,分别用jsonxml序列化的结果:

json

{"name" : "John Doe","age" : 30,"email" : "john.doe@example.com"
}

xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Person><name>John Doe</name><age>30</age><email>john.doe@example.com</email>
</Person>

哪怕没有学习过相关语法,也可以很容易读取出序列化后的内容所包含的信息。

protobuf存储的方式则是二进制形式,序列化后无法直接读取,只能看到乱码,必须由程序完成解析。相应的,protobuf的效率会比上面两者高很多,因为protobuf对数据的压缩效率极高,牺牲可视化换取高效,在一些需要高效传输数据的场景很有用。

一个序列化相关的协议,想要在计算机语言中使用,自然要配备相关的库,比如JavaScript原生对json的支持,C++通过jsoncpp库对json的支持。

protobuf由谷歌开发,谷歌也编写了相关的库,其可以支持C++JavaPythonGoC#JavaScriptPHP等主流语言,本博客以C++讲解protobuf


Linux 安装

ubuntu为例,接下来讲解如何在Linux上安装protobuf

  1. 安装依赖库

protobuf有很多依赖的库文件,执行以下指令下载所有所需的库:

apt-get install autoconf automake libtool curl make g++ unzip -y

如果是centOS,则把apt-get换成yum,另外的需要root权限。

  1. 下载安装包

protobuf的下载连接:

https://github.com/protocolbuffers/protobuf/releases

在页面中,会有很多的版本,每个版本下面的assert内有如下的安装包:

在这里插入图片描述

此时根据自己的系统架构,以及想要的版本选择对应的安装包,比如Linux x86_64架构,安装28.2版本,执行:

wget https://github.com/protocolbuffers/protobuf/releases/protoc-28.2-linux-x86_64.zip

当然也有很多其他方式,只要获取到压缩包就行。

  1. 解压安装包

最常见的安装位置是/usr/local/bin,里面存储了很多可执行文件,创建一个protobuf的目录,用于存放对应的可执行文件:

mkdir -p /usr/local/bin/protoc

随后把压缩包的内容解压到对应目录下:

unzip protoc-28.2-linux-x86_64.zip -d /usr/local/bin/protoc
  1. 添加环境变量

为了protobuf可以直接执行,要把protobufbin的路径添加到PATH环境变量中,打开~/.bashrc文件,追加以下语句到末尾:

export PATH=$PATH:/usr/local/bin/protoc/bin

最后重新加载配置文件:

source ~/.bashrc
  1. 检查安装
protoc --version

如果出现对应的版本号,那么安装成功了。


使用流程

.proto文件

就像C语言基于.c文件,C++基于.cpp文件,protobuf是基于.proto文件使用的。在.proto文件内部基于proto3语法编写文档,就可以自动生成其他语言的代码。

创建一个test.proto文件,在内部写以下内容:

syntax = "proto3";
package test_pack;message Person {string name = 1;int32 age = 2;
}// 一条注释

.proto文件基本格式如下:

  1. 语法指定行

首行固定为语法指定行,用于指定protobuf的语法版本,格式:

syntax = "版本号";

目前最新的版本为proto3,填入:

syntax = "proto3";

注意一定要在首行,哪怕上面有空行也不行,否则无法编译。

  1. package命名空间

package是一个命名空间,可以避免命名冲突,类似于C++中的namespace或者Java中的package。这是一个可选项,如果不怕命名冲突,也可以不指定。

语法:

package 命名空间;
  1. message 消息

message用于定义一个结构化的对象,其实就是一个class,内部可以定义成员。

成员字段的格式如下:

类型 成员名 = 标签;

具体类型比较多,会有专门的博客讲解protobuf的类型。标签protobuf压缩数据的重要方式,就是给每个变量指定一个编号,后续会专门讲解该内容。

标签范围: [ 1 , ( 2 29 − 1 ) ] [1, (2^{29} - 1)] [1,(2291)]

其中[19000, 19999]不可用,是保留的编号。

解析:

message Person {string name = 1;int32 age = 2;
}
  • name:字符串类型,标签为1
  • age:32位整型,标签为2

学过任何一门面向对象语言,这些内容都很好理解。

  1. 注释

.proto文件中注释格式有两种:

// 行注释/* 块注释 */

另外的,注释不占行数,也就是说首行可以是注释,不会影响syntax指定的语法标准:

// 注释...
// 注释...
// 注释...
syntax = "proto3";

以上写法是合法的,syntax前面可以有注释,但不能有空行或其他内容。


编译

编写好一个基本的.proto文件后,就可以对其进行编译,需要通过protoc指令:

protoc [--proto_path=improt路径] --cpp_out=目标路径 源路径.proto
  1. --proto_path:指定 .proto 文件的搜索路径

.proto文件中,可以通过import导入其它的.proto文件,此时就需要通过--proto_path来指定其他文件的查找路径,否则无法找到文件。

  1. --cpp_out=目标路径

--cpp_out用于指定输出C++语言的代码,目标路径是生成的代码的位置。

其他语言的选项:

选项描述
--cpp_out指定生成 C++ 代码的目录
--java_out指定生成 Java 代码的目录
--python_out指定生成 Python 代码的目录
--csharp_out指定生成 C# 代码的目录
--go_out指定生成 Go 代码的目录
--js_out指定生成 JavaScript 代码的目录
--objc_out指定生成 Objective-C 代码的目录
--php_out指定生成 PHP 代码的目录
--ruby_out指定生成 Ruby 代码的目录
--grpc_out指定生成 gRPC 服务端和客户端代码的目录
--grpc_java_out指定生成 Java gRPC 代码的目录
--swift_out指定生成 Swift 代码的目录
  1. 源文件路径

最后再指定xxx.proto源文件的路径。

如果是C++,编译后会产生如下文件:

在这里插入图片描述

至少产生了xxx.pb.ccxxx.pb.h,这些就是生成的C++代码,后续可以直接使用内部的接口。


使用

xxx.pb.h文件中至少可以找到以下内容:

namespace test_pack {class Person final : public ::google::protobuf::Message
/* @@protoc_insertion_point(class_definition:test_pack.Person) */ {public:inline Person() : Person(nullptr) {}~Person() PROTOBUF_FINAL;// ...}
}

可以看到一个命名空间域namespace test_pack,这就是之前在.proto文件中写的package test_pack,最后转化为了C++的命名空间域。

message Person也转化为了class Person,其内部实现了大量接口,包含getset等方法,以及序列化和反序列化接口。


运行机制

至此也可以看出protobuf具体是如何运行的了,如下图:

在这里插入图片描述

使用protobuf需要编写.proto文件,随后通过protoc编译器编译.proto文件,就可以得到对应语言的文件。在对应语言的文件中,会包含各类接口,最重要的就是序列化和反序列化。

.proto文件中,会有很多和计算机语言具体对应的概念,比如message对应类,package对应命名空间域,或者其他语言的包。他们都会在编译器的作用下,自动转化成对应的语言。

最后只要往自己的业务代码中引入文件,比如#include "xxx.pb.h",或者其他语言的import等,就可以直接在业务代码中使用protobuf了。


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

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

相关文章

肺结节检测-目标检测数据集(包括VOC格式、YOLO格式)

肺结节检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1hz3Y6WgWoS3Gubsw_83WnA?pwdaon1 提取码&#xff1a;aon1 数据集信息介绍&#xff1a; 共有 1180 张图像和一一对应的标注文件 标注…

【**倒计时,人工智能的ASI时代几年内将至-samaltman深夜发文预言**】

在未来的几十年里&#xff0c;我们将能够做到我们的祖辈认为像魔术一样的事情。 这是Sama Ltman博文的第一句话。技术进步加速&#xff1a;随着时间的推移&#xff0c;人类的能力显著提高&#xff0c;我们能够完成前人认为不可能的事情。他认为&#xff1a; 我们的能力增强不…

数据结构-2.9.双链表

一.双链表与单链表的对比&#xff1a; 二.双链表的初始化(带头结点)&#xff1a; 1.图解&#xff1a; 2.代码演示&#xff1a; #include<stdio.h> #include<stdlib.h> ​ //定义双链表结构体 typedef struct DNode {int data;struct DNode *prior;//前驱指针即指…

数据结构~二叉搜索树

文章目录 一、二叉树搜索的概念二、二叉树搜索的结构二叉树搜索的性能分析二叉树搜索的插入二叉树搜索的查找二叉树搜索的删除 三、二叉搜索树key和key/value使用场景四、二叉树搜索的练习将二叉搜索树就地转化为已排序的双向循环链表从前序与中序遍历序列构造二叉树二叉树的前…

2024最新盘点:90%的工厂都在用的仓库管理系统有哪些?

有很多老板看见同行都在用仓库管理系统来管理库存、采购等工作&#xff0c;也想入手一个&#xff0c;但是不知从何下手&#xff0c;又很苦恼怎么才能选择适合自己企业的系统。 不用担心&#xff0c;本篇文章将会从市面上很多老板都在用的WMS系统&#xff0c;从适用范围、核心功…

智能密码、指纹锁语音芯片ic方案 可存放40s语音内容 NVD语音芯片

随着科技的飞速发展&#xff0c;智能家居安全领域迎来了前所未有的变革。智能密码与指纹锁作为现代家庭安全防护的重要一环&#xff0c;其背后的语音芯片IC开发更是这一变革中的关键技术突破。 智能密码、指纹锁语音芯片ic方案 选型与简介&#xff1a; NVD语音芯片是一款低成…

《ESP32调试异常集锦》之:程序编译失败,提示undefined reference to `dedic_gpio_bundle_write‘

项目场景&#xff1a; 硬件&#xff1a;ESP32-LyraT-Mini V1.2开发板&#xff0c;使用的是ESP32-WROVER-E 模组。 程序&#xff1a;基于soft_i2c示例程序修改协议内容实现与TM1640通信测试 问题描述 编译失败&#xff0c;"full clean"后重新编译依旧失败。没有语法…

EasyGBD国标GB28181设备端,支持GB28181-2016、GB28181-2022

功能概要&#xff1a; 功能概述&#xff1a;EasyGBD是GB/T28181 Device的简称&#xff0c;指国标GB28181协议的设备端。EasyGBD功能组件支持Windows、Linux、Android、iOS、ARM等所有平台&#xff0c;可兼容国标GB28181-2011、GB28181-2016的全部功能。 操作系统&#xff1a;任…

SOMEIP_ETS_127: SD_Multicast_FindService

测试目的&#xff1a; 验证DUT能够对10个多播FindService消息做出响应&#xff0c;这些消息每100ms发送一次&#xff0c;请求有效的服务/实例ID&#xff08;取决于DUT&#xff09;&#xff0c;DUT需要使用单播OfferService消息来回答。 描述 本测试用例旨在确保DUT能够正确处…

爆火南卡开放式耳机,音质性能霸榜TOP1,行业唯一达专业HiFi级音质标准!

爆火南卡开放式耳机&#xff0c;音质性能霸榜TOP1&#xff0c;行业唯一达专业HiFi级音质标准&#xff01; 随着科技的不断进步&#xff0c;耳机市场迎来了又一次革命性的创新。南卡&#xff08;NANK&#xff09;品牌近日宣布&#xff0c;其最新力作——南卡Ultra耳夹开放式耳机…

阿里发电预测模型:FusionSF

论文《FusionSF: Fuse Heterogeneous Modalities in a Vector Quantized Framework for Robust Solar Power Forecasting》 目前的研究主要依赖于历史太阳能数据或单模态格式的数值天气预报&#xff0c;忽略了不同模态提供的补充信息。 本文提出一个多模态融合框架&#xff0…

element下拉框联动 或 多选 回显数据后页面操作不生效问题解决

第一种:多选回显不生效 解决方式: 代码: <el-form-item label"系统" prop"Key"> <el-select v-model"addForm.Key" multiple placeholder"请选择" change"$forceUpdate()"> <el-option v-for"item …

史上最详细泛微Ecology9安装教程及安装包(含注册)

在现代企业中&#xff0c;泛微Ecology9 已成为高效的办公自动化管理系统之一&#xff0c;帮助企业在流程管理、信息协同等方面实现快速发展。本篇文章将为您详细介绍泛微Ecology9的安装过程&#xff0c;并提供最新的安装包下载&#xff0c;包含完整的注册信息&#xff0c;助您快…

盲盒小程序|探寻盲盒乐趣,开发专属商城

随着潮流文化的不断发展&#xff0c;盲盒作为一种独特的消费模式&#xff0c;越来越受到年轻人的喜爱。在盲盒玩具的世界里&#xff0c;每一次开启都像是打开神秘宝盒&#xff0c;不知道会有什么惊喜等待着你。无论是收集可爱的公仔&#xff0c;还是寻找珍稀的限定版&#xff0…

Vulnhub:Fowsniff 1

靶机下载地址 信息收集 主机发现 nmap 192.168.31.0/24 -Pn -T4 靶机ip&#xff1a;192.168.31.134 端口扫描 nmap 192.168.31.134 -A -p- -T4 开放端口22(ssh)、80(http)&#xff0c;和两个明文传输的邮件端口110(pop3)、143(imap)。 HTTP 访问http://192.168.31.134。…

线程池工作原理?

线程池的工作原理&#xff1a; 当任务过来时&#xff0c;如果线程池中的线程数小于核心线程数&#xff0c;就创建线程。&#xff08;默认情况下&#xff0c;线程池不会预先创建线程&#xff0c;但可以配置&#xff09;当核心线程数满了以后&#xff0c;提交过来的任务会放到阻塞…

公司可以看到员工电脑在干嘛吗?四种监控员工电脑的方式

想象一下&#xff0c;你刚打开电脑&#xff0c;准备浏览最新的娱乐新闻&#xff0c;突然想到&#xff1a;“我的老板能看到我在干嘛吗&#xff1f;” 随着企业对工作效率和信息安全的关注日益增加&#xff0c;越来越多的公司开始采用各种方式来监控员工的电脑使用情况。 那么…

Java语言程序设计基础篇_编程练习题**18.38 (递归树)

目录 题目&#xff1a;**18.38 (递归树) 代码示例 代码逻辑解释 类定义和变量初始化 main 方法 start 方法 drawRecursiveTree 方法 输出结果 题目&#xff1a;**18.38 (递归树) 编写一个程序来显示一个递归树&#xff0c;如图18-20所示 代码示例 编程练习题18_38Re…

git push错误:Out of memory, malloc failed (tried toallocate 947912704 bytes)

目录 一、错误截图 二、解决办法 一、错误截图 因项目文件过大&#xff0c;http.postBuffer设置的内存不够&#xff0c;所以报错。 二、解决办法 打开cmd窗口&#xff0c;执行如下命令即可 git config --global http.postBuffer 1024000000 如图所示 执行完成以后&#…

ABAP 学习t-code DWDM

ABAP 学习t-code DWDM &#xff0c;里面有很多例子展示&#xff0c;且能看到源代码