Protobuf:基本概念与使用流程

news2024/9/24 16:15:47

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.coloradmin.cn/o/2160785.html

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

相关文章

召回04 离散特征的处理

推荐系统会将一个id映射成一个向量 Qne-Hot编码 Embedding(嵌入)&#xff1a; 把每个类别映射成一个低维的稠密向量

Drive.js 的一些 Api 使用记录

文章目录 2024 年 drive.js 的基础使用想在下一步的时候处理些逻辑呢&#xff1f;(同步)Element 的各种选择器 2024 年 drive.js 的基础使用 安装就跳过了 npm install driver.js &#xff0c;一行代码就可以搞定 官网的 Basic Usage 基础使用的截图如下&#xff1a; 想在下…

C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究

思考这样一串代码的运行结果&#xff1a; #include <iostream> using namespace std; class Person { public:~Person() { cout << "~Person()" << endl; } }; class Student:public Person { public:~Student() { cout << "~Student(…

线程池工作原理?

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

Axure9破解

1.下载安装包 通过百度网盘分享的文件&#xff1a;Axure RP 9.zip 链接&#xff1a;https://pan.baidu.com/s/1Lcu-gg4qF8tTkOlt7bC2ww?pwdwmqq 提取码&#xff1a;wmqq 2.设置登录以及破解码 位置&#xff1a;帮助-管理授权-添加key Licensee&#xff1a;123456 Key&#…

Ping32:一站式终端安全解决方案,企业安心之选

在数字化时代&#xff0c;企业的终端安全面临着前所未有的挑战。随着网络威胁的日益复杂化和多样化&#xff0c;如何确保终端设备的安全稳定运行&#xff0c;保护企业敏感数据不被泄露&#xff0c;成为了每个企业必须面对的重要课题。正是在这样的背景下&#xff0c;Ping32作为…

第十四届蓝桥杯嵌入式国赛

一. 前言 本篇博客主要讲述十四届蓝桥杯嵌入式的国赛题目&#xff0c;包括STM32CubeMx的相关配置以及相关功能实现代码以及我在做题过程中所遇到的一些问题和总结收获。如果有兴趣的伙伴还可以去做做其它届的真题&#xff0c;可去 蓝桥云课 上搜索历届真题即可。 二. 题目概述 …

探索LLM中的CoT链式推理:ECHO方法深度解读

近年来&#xff0c;随着大型语言模型&#xff08;LLMs&#xff09;的快速发展&#xff0c;如何有效利用这些模型进行复杂任务的推理成为了研究热点。其中&#xff0c;链式思考&#xff08;Chain-of-Thought, CoT&#xff09;推理方法作为一种有效的策略&#xff0c;能够显著提升…

Redhat 6,7,8系(复刻系列) 一键部署Oracle12c zip

Oracle12c前言 Oracle 12c是甲骨文公司推出的一款关系数据库管理系统,它引入了多项创新特性,如多租户架构、大数据处理和云部署,适用于企业级应用。以下是Oracle 12c的详细介绍: Oracle 12c的主要特点 高性能:通过多线程处理、自动优化等技术,提高了数据库的查询和处理…

云栖大会 | 天润融通发布微藤智能体平台,中国客户联络正式进入“智能体时代”

9月19日&#xff0c;以“云启智跃&#xff0c;产业蝶变”为主题的2024云栖大会在杭州正式开幕。大会持续三天&#xff0c;聚焦AI时代的技术升级与实践应用&#xff0c;设有三大主论坛、400多个分论坛&#xff0c;并开放4万平方米的智能科技展区&#xff0c;展示全球百余款AI应用…

CHARLS数据库系列教程(3)---绘制(加权和不加权)基线表一

CHARLS 是一项具备中国大陆 45 岁及以上人群代表性的追踪调查&#xff0c;旨在建设一个高质量的公共微观数据库&#xff0c;采集的信息涵盖社会经济状况和健康状况等多维度的信息&#xff0c;以满足老龄科学研究的需要。 为利用国际上最佳的数据采集方式&#xff0c;并确保研究…

2024年工业制造企业CRM研究报告:需求清单、市场格局、案例分析

我国是世界上产业体系最完备的国家&#xff0c;拥有全球规模最大、门类最齐全的生产制造体系&#xff0c;在500种主要工业产品中&#xff0c;有四成以上产品产量位居全球第一。2023年制造业增加值达33万亿元&#xff0c;占世界的比重稳定在30%左右&#xff0c;我国制造业增加值…

Register Two Point Sets 注册两个点集

文章目录 Register Two Point Sets 注册两个点集Visualize Gradient Descent 可视化梯度下降Hyperparameter Search 超参数搜索JensenHavrdaCharvatTsallisPointSetToPointSetMetricv4类说明 原文url: https://examples.itk.org/src/registration/metricsv4/registertwopointse…

基于 BERT 的自定义中文命名实体识别实现

基于 BERT 的自定义中文命名实体识别实现 在自然语言处理中,命名实体识别(Named Entity Recognition,NER)是一项重要的任务,旨在识别文本中的特定实体,如人名、地名、组织机构名等。本文将介绍如何使用 BERT 模型实现自定义中文命名实体识别,并提供详细的代码分析和解读…

乐(智)尚代驾~~--------Day5----司机认证篇~

前言&#xff1a; Hello亲爱的uu们&#xff0c;在读过了一个愉快的周末后&#xff08;摸鱼了一会&#xff09;&#xff0c;我又回来更新啦&#xff0c;感谢uu们的阅读&#xff0c;话不多说~ 司机认证 当司机点击开始接单的时候&#xff0c;会先判断该司机有没有通过认证&…

跨平台数据库工具DataGrip v2024.2全新发布——增加智能刷新功能

DataGrip 是一个跨平台的数据库工具可在Windows&#xff0c;OS X 和 Linux上使用。同时支持多种数据库&#xff0c;包含了SQL Server&#xff0c;Oracle&#xff0c;PostgreSQL&#xff0c;MySQL&#xff0c;DB2&#xff0c;Sybase&#xff0c;SQLite&#xff0c;Derby&#xf…

DQL学习

一、基础查询 1.查询多个字段 select 字段列表 from 表名; select * from 表名;-- 查询所有数据 但不建议使用&#xff01;&#xff01;&#xff01;&#xff01; 2.去除重复记录 select DISTINCT 字段列表 from 表名; 3.起别名 as&#xff1b;as也可以省略但中间要加空…

导入时,文档模板不被下载

问题描述 提示&#xff1a;这里描述项目中遇到的问题&#xff1a; 这是个SSM项目&#xff0c;以前经常遇到这个问题&#xff0c;今天有幸记录下来 [ERROR][o.a.s.r.StreamResult] Can not find a java.io.InputStream with the name [downLoadFile] in the invocation stack…

目标检测系列(一)什么是目标检测

目录 一、相关名词解释 二、目标检测算法 三、目标检测模型 四、目标检测应用 五、目标检测数据集 六、目标检测常用标注工具 一、相关名词解释 关于图像识别的计算机视觉四大类任务&#xff1a; 分类&#xff08;Classification&#xff09;&#xff1a;解决“是什么&…

【Linux 报错】“userdel: user xxxx is currently used by process xxx”

问题产生的原因&#xff1a; 多个用户后嵌套登陆导致删除某用户时&#xff0c;这个用户还没退出导致无法删除的问题。 例如&#xff1a;你在普通用户 A 的账户下&#xff0c;切换超级用户 root 执行删除普通用户 A 的账户&#xff0c;此时普通用户 A还在当前进程中运行&#…