热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入探索protobuf协议学习笔记

目录简介官方API解读(C)定义一个ProtocolFormat编译ProtocolBuffersTheProtocolBufferAPI解析和序列化官方示例注释总结你知道的越多&

目录

    • 简介
    • 官方API解读(C++)
      • 定义一个Protocol Format
      • 编译Protocol Buffers
      • The Protocol Buffer API
      • 解析和序列化
    • 官方示例注释
    • 总结


你知道的越多,你知道的越少。


简介

什么是protobuf?

protocol buffers 是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它可用于(数据)通信协议、数据存储等
在网络通信和通用数据交换等应用场景中经常使用的技术是 JSONXML
Protocol Buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松的在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不破坏由旧数据结构编译的已部署程序

其具有以下特点:

  • 语言无关、平台无关。即 ProtoBuf 支持 JavaC++Python 等多种语言,支持多个平台
  • 高效。即比 XML 更小(3 ~ 10倍)、更快(20 ~ 100倍)、更为简单
  • 扩展性、兼容性好。你可以更新数据结构,而不影响和破坏原有的旧程序

官网:protobuf官网

官方示例:官方示例下载

GitHub源码:protobuf-GitHub

官方API解读(C++)

大致步骤:

  • 定义一个.proto文件
  • 使用protocol buffer编译器
  • 使用c++ API读写这个文件

定义一个Protocol Format

定义一个Protocol模板

message Example1 {optional string stringVal = 1;optional bytes bytesVal = 2;message EmbeddedMessage {int32 int32Val = 1;string stringVal = 2;}optional EmbeddedMessage embeddedExample1 = 3;repeated int32 repeatedInt32Val = 4;repeated string repeatedStringVal = 5;
}

message 关键字后跟上消息名称

message xxx {// do something
}

之后我们在其中定义了 message 具有的字段,形式为:

message xxx {// 字段规则:required -> 字段只能也必须出现 1 次// 字段规则:optional -> 字段可出现 0 次或1次// 字段规则:repeated -> 字段可出现任意多次(包括 0)// 类型:int32、int64、sint32、sint64、string、32-bit ....// 字段编号:0 ~ 536870911(除去 1900019999 之间的数字)字段规则 类型 名称 = 字段编号;
}

关于保留字requiredoptionalrepeated可见

  • required:必须为该字段提供一个值,否则该消息将被视为“未初始化”
  • optional:该字段可能被设置,也可能没有设置
  • repeated:该字段可以重复任何次数(包括零)

更多介绍可见官网

编译Protocol Buffers

我们在 .proto 文件中定义了数据结构,这些数据结构是面向开发者和业务程序的,并不面向存储和传输

当需要把这些数据进行存储或传输时,就需要将这些结构数据进行序列化、反序列化以及读写。那么如何实现呢?不用担心, ProtoBuf将会为我们提供相应的接口代码。如何提供?答案就是通过 protoc 这个编译器

编译器下载地址:protoc编译器下载

protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto

他最后会生成两个文件

  • addressbook.pb.h:声明生成的类的头文件
  • addressbook.pb.cc:其中包含您的类的实现

The Protocol Buffer API

对于一个message,protoc都会生成一个struct(class),而struct中的属性字段,都会自动的生成一些访问器

/* 是否存在这个属性 */inline bool has_name() const;/* 清除这个属性 */inline void clear_name();/* 获取引用 */inline const ::std::string& name() const;/* 设置这个属性的值,只有字段是string才会有 */inline void set_name(const ::std::string& value);/* 设置这个属性的值 */inline void set_name(const char* value);/* 获取一个指针,只有字段是string才会有 */inline ::std::string* mutable_name();

类中的方法本身是隐式的内联函数inline

而对于一些可重复的字段repeated,会生成以下字段

/* 这个message的数量 */inline int phones_size() const;/* 清除这个message */inline void clear_phones();/* 正常取值 */inline const ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >& phones() const;/* 获取一个指针 */inline ::google::protobuf::RepeatedPtrField< ::tutorial::Person_PhoneNumber >* mutable_phones();/* 根据索引获取指定的字段 */inline const ::tutorial::Person_PhoneNumber& phones(int index) const;/* 根据索引更新指定的字段的指针 */inline ::tutorial::Person_PhoneNumber* mutable_phones(int index);/* 在可重复essage中添加一个新的值*/inline ::tutorial::Person_PhoneNumber* add_phones();

更详细可见C&#43;&#43; generated code reference

还有一些标准接口

每个消息类还包含许多其他方法&#xff0c;让你检查或操作整个消息&#xff0c;包括:

  • bool IsInitialized() const;&#xff1a; 检查是否设置了所有必需的字段。
  • string DebugString() const;&#xff1a;返回人类可读的消息表示形式&#xff0c;对调试特别有用。
  • void CopyFrom(const Person& from);&#xff1a;使用给定消息的值覆盖消息。
  • void Clear();&#xff1a;将所有元素清除回空状态

解析和序列化

最后&#xff0c;每个协议缓冲区类都有使用协议缓冲区二进制格式编写和读取所选类型的消息的方法。这些包括&#xff1a;

  • bool SerializeToString(string* output) const;&#xff1a;对消息进行序列化并将字节存储在给定字符串中。注意&#xff0c;字节是二进制的&#xff0c;不是文本;我们只将string类用作方便的容器。
  • bool ParseFromString(const string& data);&#xff1a;解析来自给定字符串的消息
  • bool SerializeToOstream(ostream* output) const;&#xff1a;将消息写入给定的c&#43;&#43; ostream。
  • bool ParseFromIstream(istream* input);&#xff1a;从给定的c&#43;&#43; istream中获取消息。

官方示例注释

#include
#include
#include
#include "addressbook.pb.h"
using namespace std;// 该函数根据用户输入填充Person消息
void PromptForAddress(tutorial::Person* person) {// do something
}int main(int argc, char* argv[]) {//验证我们所链接的库的版本//与我们编译的头文件版本兼容。GOOGLE_PROTOBUF_VERIFY_VERSION;// 对AddressBook进行一个实例化tutorial::AddressBook address_book;{fstream input(argv[1], ios::in | ios::binary);if (!input) {cout << argv[1] << ": File not found. Creating a new file." << endl;} else if (!address_book.ParseFromIstream(&input)) {cerr << "Failed to parse address book." << endl;return -1;}}PromptForAddress(address_book.add_people());{// Write the new address book back to disk.fstream output(argv[1], ios::out | ios::trunc | ios::binary);if (!address_book.SerializeToOstream(&output)) {cerr << "Failed to write address book." << endl;return -1;}}// 可选:删除libprotobuf分配的所有全局对象。google::protobuf::ShutdownProtobufLibrary();return 0;
}

总结


  • XMLJSONProtoBuf都具有数据结构化和数据序列化的能力
  • XMLJSON 更注重数据结构化&#xff0c;关注人类可读性和语义表达能力。ProtoBuf 更注重数据序列化&#xff0c;关注效率、空间、速度&#xff0c;人类可读性差&#xff0c;语义表达能力不足&#xff08;为保证极致的效率&#xff0c;会舍弃一部分元信息&#xff09;
  • ProtoBuf 的应用场景更为明确&#xff0c;XMLJSON 的应用场景更为丰富

只能说&#xff0c;各有所长&#xff0c;各有所短吧。

参考&#xff1a;

  1. 深入 ProtoBuf - 简介
  2. protobuf官网

推荐阅读
  • 使用nodejs爬取b站番剧数据,计算最佳追番推荐
    本文介绍了如何使用nodejs爬取b站番剧数据,并通过计算得出最佳追番推荐。通过调用相关接口获取番剧数据和评分数据,以及使用相应的算法进行计算。该方法可以帮助用户找到适合自己的番剧进行观看。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Java自带的观察者模式及实现方法详解
    本文介绍了Java自带的观察者模式,包括Observer和Observable对象的定义和使用方法。通过添加观察者和设置内部标志位,当被观察者中的事件发生变化时,通知观察者对象并执行相应的操作。实现观察者模式非常简单,只需继承Observable类和实现Observer接口即可。详情请参考Java官方api文档。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • 本文记录了在vue cli 3.x中移除console的一些采坑经验,通过使用uglifyjs-webpack-plugin插件,在vue.config.js中进行相关配置,包括设置minimizer、UglifyJsPlugin和compress等参数,最终成功移除了console。同时,还包括了一些可能出现的报错情况和解决方法。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
author-avatar
mobiledu2502931467
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有