1.Protobuf入门:在linux下编译使用protobuf
2.在C++中使用Protobuf
3.七爪源码:学习用于序列化结构化数据的源码协议缓冲区 (Protobuf) — 第 1 部分
4.使用protobuf实现序列化与反序列化
5.网络数据通信—ProtoBuf实现序列化和反序列化
6.1.1.1模型描述与序列化方法之Protobuf(一):初步使用
Protobuf入门:在linux下编译使用protobuf
Google Protocol Buffer(简称Protobuf)是一种由Google公司内部开发的数据标准,用于数据序列化。分析广泛应用于数据存储和远程过程调用(RPC)系统。源码它具备语言无关性、分析平台无关性和可扩展性,源码支持C++、分析源码编程器简单动画Java和Python等语言。源码
编译源码包:从GitHub下载Protobuf的分析源代码,以2.5.0版本为例。源码解压后,分析执行配置编译命令,源码创建文件。分析编译后,源码文件夹中将包含bin、分析include和lib目录。源码
测试工程:将include目录下的文件按目录结构和lib/libprotobuf.a复制到测试目录。定义结构化数据Content,包含id(int)、str(string)和opt(可选成员)。使用protoc程序将Mymessage.proto文件编译成目标语言,生成Mymessage.pb.h和Mymessage.pb.cc文件。
将编译后的Mymessage.pb.o文件与Writer.cpp文件一起编译,生成log文件。Reader从log文件读取,反序列化后获得结构化数据。
Protobuf的优点在于高效、紧凑的二进制数据序列化方式,使其适合数据存储和RPC通信。然而,它缺乏复杂概念表示的能力,与XML相比在通用性上仍有不足。XML自解释性使其在文本描述方面优于Protobuf。
高级应用包括嵌套消息、Import Message和动态编译。嵌套消息如Person包含PhoneNumber,用于Person中的phone域。Import Message允许在包中定义公用消息,通过包引入使用。动态编译允许在运行时处理未知的.proto文件。
编写新编译器:利用Google Protocol Buffer源代码中的protoc编译器,可以开发支持其他语言的workflow 源码编译器。通过实现CodeGenerator派生类,实现代码生成功能。
Protobuf的编码方式使用Varint表示数字,节省空间。Varint用一个或多个字节表示数字,值越小字节越少。消息序列化为紧凑的二进制数据流,无需分隔符,可优化大小。
在C++中使用Protobuf
ProtoBuf的定义和描述:
Protocol Buffers是一种语言无关、平台无关、可扩展的序列化结构数据的方法,它适用于(数据)通信协议、数据存储等。
Protocol Buffers是一种灵活、高效、自动化的结构数据序列化方法,类似于XML,但比XML更小(3 ~ 倍)、更快( ~ 倍)、更简单。
你可以定义数据的结构,然后使用特殊生成的源代码轻松地在各种数据流中使用各种语言进行编写和读取结构数据。你甚至可以更新数据结构,而不会破坏由旧数据结构编译的已部署程序。
使用 ProtoBuf教程:
在了解了ProtoBuf的基本概念之后,我们将具体了解如何使用ProtoBuf。
第一步,创建.proto文件,定义数据结构,如下所示:
我们在上例中定义了一个名为Person的消息,语法很简单,message关键字后跟消息名称。之后我们在其中定义了message具有的字段,形式为:
第二步,protoc编译.proto文件生成读写接口:
在.proto文件中定义了数据结构,这些数据结构是面向开发者和业务程序的,并不面向存储和传输。当需要把这些数据进行存储或传输时,就需要将这些结构数据进行序列化、少年源码反序列化以及读写。ProtoBuf提供相应的接口代码,可以通过protoc这个编译器来生成相应的接口代码,命令如下:
生成的.h,.cpp文件为person.pb.h,person.pb.cpp,且.h的定义与proto文件的内容相关联:
第三步,编写C++业务代码:
c++业务代码对应的CMakeLists.txt为:
参考链接:
七爪源码:学习用于序列化结构化数据的协议缓冲区 (Protobuf) — 第 1 部分
在深入探讨 Protocol Buffers 之前,让我们先了解序列化和反序列化的基本概念。序列化是指将对象转换为线性字节序列以便存储或传输到另一位置的过程。反序列化则是获取存储信息并从中重新创建对象的过程。随着数据的不断增长,序列化和反序列化的数据方法也在不断发展。
CSV(逗号分隔值)是一种易于解析和读取的方法,但存在一些缺点,如必须推断数据类型且不保证。当数据包含逗号且列名存在或不存在时,解析变得困难。关系表定义添加了类型信息,数据是完全类型化的,且可以放入表格中。然而,数据必须是平面的,并且不同数据库的数据定义各不相同。JSON(JavaScript 对象表示法)是一种广泛接受的网络格式,数据可以采用任意形式,易于被多数编程语言读取,并且可通过网络轻松共享。然而,JSON 数据没有模式强制,且 JSON 对象大小较大,因为重复的键。
XML(可扩展标记语言)使用类似于 JSON 的元标记,但带有结束标记。由于它们具有结束标记,因此与 JSON 相比,它们的大小要大得多。
Protocol Buffers(或 Protobuf)是一种语言中立、平台中立的可扩展数据序列化协议,不同于 JSON 或 XML。源码126Protobuf 不适合人类使用,因为序列化数据是编译后的字节,难以供人类阅读。它是 Google 用于序列化结构化数据的机制。
Protocol Buffers 的优点包括易于跨编程语言共享数据。在 .proto 文件上运行 Protocol Buffers 编译器时,编译器会以所选语言生成代码。我们只需使用在 .proto 文件中描述的消息类型,包括获取、设置字段值、将消息序列化到输出流以及从输入流解析消息。
为了更高效地设计 .proto 文件,Google 提供了样式指南,应尽量遵守。标准文件格式包括许可证标题(如有适用)、文件概述、语法、包装、导入(排序)、文件选项和其他内容。在 Protocol Buffers 中,字段标签非常重要。最小标签值可以是 1,最大标签值可以是 2²⁹–1 或 ,,。编号从 1 到 的标签使用 1 个字节,而编号从 到 的标签使用 2 个字节。对经常填充的字段使用 1 到 个标签号。
Protocol Buffers 支持多种字段类型,如布尔型、字符串、字节、重复字段、枚举等。在 Protocol Buffers 中,字段名称不重要,它们仅在编程中引用字段时重要。字段标签很重要,最小标签值可以是 1,最大标签值可以是 ,,。编号从 1 到 的scum源码标签使用 1 个字节,而编号从 到 的标签使用 2 个字节。对经常填充的字段使用 1 到 个标签号。
枚举允许我们定义事先知道的一个字段可以取的所有值。默认字段值为布尔型的假、数字的 0、字符串的空字符串、字节的空字节、重复的空列表和枚举的第一个值。我们还可以使用其他消息类型作为字段类型。嵌套类型有助于避免命名冲突并加强局部性。在下一篇文章中,我们将探讨 Protocol Buffers 的高级概念。
使用protobuf实现序列化与反序列化
protobuf是用来干嘛的?
protobuf是一种用于对结构数据进行序列化的工具,从而实现数据存储和交换。(主要用于网络通信中收发两端进行消息交互。所谓的“结构数据”是指类似于struct结构体的数据,可用于表示一个网络消息。当结构体中存在函数指针类型时,直接对其存储或传输相当于是“浅拷贝”,而对其序列化后则是“深拷贝”。)
序列化:将结构数据或者对象转换成能够用于存储和传输的格式。 反序列化:在其他的计算环境中,将序列化后的数据还原为数据结构和对象。
从“序列化”字面上的理解,似乎使用C语言中的struct结构体就可以实现序列化的功能:将结构数据填充到定义好的结构体中的对应字段即可,接收方再对结构体进行解析。
在单机的不同进程间通信时,使用struct结构体这种方法实现“序列化”和“反序列化”的功能问题不大,但是,在网络编程中,即面向网络中不同主机间的通信时,则不能使用struct结构体,原因在于:
(1)跨语言平台,例如发送方是用C语言编写的程序,接收方是用Java语言编写的程序,不同语言的struct结构体定义方式不同,不能直接解析;
(2)struct结构体存在内存对齐和CPU不兼容的问题。
因此,在网络编程中,实现“序列化”和“反序列化”功能需要使用通用的组件,如 Json、XML、protobuf 等。
① 性能高效: 与XML相比,protobuf更小(3 ~ 倍)、更快( ~ 倍)、更为简单。
② 语言无关、平台无关: protobuf支持Java、C++、Python等多种语言,支持多个平台。
③ 扩展性、兼容性强: 只需要使用protobuf对结构数据进行一次描述,即可从各种数据流中读取结构数据,更新数据结构时不会破坏原有的程序。
Protobuf与XML、Json的性能对比:
测试万次序列化:
测试万次反序列化:
protobuf 2 中有三种数据类型限定修饰符:
required表示字段必选,optional表示字段可选,repeated表示一个数组类型。
其中, required 和 optional 已在 proto3 弃用了。
protobuf中常用的数据类型:
下载protobuf压缩包后,解压、配置、编译、安装,即可使用protoc命令查看Linux中是否安装成功:
使用protobuf时,需要先根据应用需求编写 .proto 文件定义消息体格式,例如:
其中,syntax关键字表示使用的protobuf的版本,如不指定则默认使用 "proto2";package关键字表示“包”,生成目标语言文件后对应C++中的namespace命名空间,用于防止不同的消息类型间的命名冲突。
然后使用 protobuf编译器(protoc命令)将编写好的 .proto 文件生成目标语言文件(例如目标语言是C++,则会生成 .cc 和 .h 文件),例如:
其中:
$SRC_DIR表示 .proto文件所在的源目录; $DST_DIR表示生成目标语言代码的目标目录; xxx.proto表示要对哪个.proto文件进行解析; --cpp_out表示生成C++代码。
编译完成后,将会在目标目录中生成xxx.pb.h和xxx.pb.cc文件,将其引入到我们的C++工程中即可实现使用protobuf进行序列化:
在C++源文件中包含xxx.pb.h头文件,在g++编译时链接xxx.pb.cc源文件即可:
在protobuf源码中的/examples 目录下有官方提供的protobuf使用示例:addressbook.proto
参考官方示例实现C++使用protobuf进行序列化和反序列化:
addressbook.proto :生成的addressbook.pb.h 文件内容摘要:add_person.cpp :
输出结果:
三种序列化的方法没有本质上的区别,只是序列化后输出的格式不同,可以供不同的应用场景使用。 序列化的API函数均为const成员函数,因为序列化不会改变类对象的内容,而是将序列化的结果保存到函数入参指定的地址中。
.proto文件中的option选项用于配置protobuf编译后生成目标语言文件中的代码量,可设置为SPEED, CODE_SIZE, LITE_RUNTIME 三种。 默认option选项为 SPEED,常用的选项为 LITE_RUNTIME。
三者的区别在于:
① SPEED(默认值): 表示生成的代码运行效率高,但是由此生成的代码编译后会占用更多的空间。
② CODE_SIZE: 与SPEED恰恰相反,代码运行效率较低,但是由此生成的代码编译后会占用更少的空间,通常用于资源有限的平台,如Mobile。
③ LITE_RUNTIME: 生成的代码执行效率高,同时生成代码编译后的所占用的空间也非常少。 这是以牺牲Protobuf提供的反射功能为代价的。 因此我们在C++中链接Protobuf库时仅需链接libprotobuf-lite,而非protobuf。
SPEED 和 LITE_RUNTIME相比,在于调试级别上,例如 msg.SerializeToString(&str;); 在 SPEED 模式下会利用反射机制打印出详细字段和字段值,但是 LITE_RUNTIME 则仅仅打印字段值组成的字符串。
因此:可以在调试阶段使用 SPEED 模式,而上线以后提升性能使用 LITE_RUNTIME 模式优化。
最直观的区别是使用三种不同的 option 选项时,编译后产生的 .pb.h 中自定义的类所继承的 protobuf类不同:
① protobuf 将消息里的每个字段进行编码后,再利用TLV或者TV的方式进行数据存储; ② protobuf 对于不同类型的数据会使用不同的编码和存储方式; ③ protobuf 的编码和存储方式是其性能优越、数据体积小的原因。
网络数据通信—ProtoBuf实现序列化和反序列化
Protobuf实现序列化和反序列化 本文将介绍如何通过Protobuf实现网络数据通信,具体案例中我们构建一个通讯录应用,包含客户端和服务器端的交互。主要需求包括: 客户端可执行的操作:新增联系人、删除联系人、查询通讯录列表、查询联系人详细信息。 服务器端提供增删查能力,并确保数据持久化。 客户端与服务器间交互数据使用Protobuf。 环境搭建 选择cpp-/yhirose/cpp-... CentOS环境注意事项 在CentOS下,若使用自带的g++版本(如4.8.5,发布于年),在编译项目时可能遇到问题。解决方法是升级gcc/g++至更高版本。 约定双端交互接口新增联系人
删除联系人
查询通讯录列表
查询联系人详细信息
约定双端交互req/resp 设计了多个protobuf文件用于定义请求和响应结构,包括base_response.proto、add_contact_request.proto至find_all_contacts_response.proto等。 相关视频推荐高性能服务器通信协议设计的奥秘:XML、JSON、Protobuf性能对比分析
Protobuf序列化协议工程应用方法和实践分析
qq微信即时通讯技术细节:方案选择
C/C++ Linux服务器架构师学习资料分享群:(包含C/C++、Linux、golang等技术资料)
客户端代码实现main.cc:主程序
ContactException.h:异常类定义
ContactsServer.h:客户端通讯录服务端定义
ContactsServer.cc:客户端通讯录服务实现
服务端代码实现定义通讯录结构(contacts.proto)
main.cc:服务端主程序
ContactException.h:异常类定义
ContactsServer.h:通讯录服务定义
ContactsServer.cc:通讯录服务实现
Utils.h:工具类定义
ContactsMapper.h:数据持久化接口定义
ContactsMapper.cc:数据持久化接口实现
注:在实际应用中,应将通讯录数据存储至数据库,此处为简化流程,以本地文件作为数据存储。1.1.1模型描述与序列化方法之Protobuf(一):初步使用
protobuf的使用流程相对直接,主要包括安装、编译.proto文件和生成可执行文件。本文将主要关注.proto文件的语法规则。1. 安装与配置
尽管具体版本需要在实际操作中指定,但安装过程通常是下载并执行相应的protobuf可执行文件protoc。2. 编译.proto文件
将编写好的.proto文件通过protoc工具编译,生成工程所需的pb.h和pb.cpp源文件。命令行操作简单,只需指定输入目录、输出目录和要编译的.proto文件名。3. 生成可执行文件
将编译得到的.pb.h和.pb.cpp文件与你的cpp源码一起编译,使用pkg-config提供的protobuf编译参数。4. Proto文件语法详解
Proto文件的基本结构为"字段规则 数据类型 名称 = 域值 [选项 = 选项值];"。字段规则有repeated、optional、required和reserved。例如:repeated string name = 1; 表示可多次出现,包括0次。
optional string name = 1 [default ""]; 表示0次或1次出现,可指定默认值。
required string name = 1; 必须出现1次。
reserved name; 表示废弃,用于迭代更新。
数据类型分为基本类型(如float、uint、string、bool)和复合类型(如message、enum、oneof和map)。message类似C++中的类,而enum则对应枚举。5. 选项与优化
选项如default和packed用于设置默认值和优化编码效率,而deprecated用于标记过时属性。6. 其他
高级功能如extensions、service和options通常不常用,相关内容请参考官方文档。7. 代码接口
编译后的接口结构在官方文档中详细说明,此处不再赘述。一文读懂——Protobuf
快速理解Protocol Buffers
Protocol Buffers(简称Protobuf),是Google为内部通信和数据存储设计的一种高效轻量级的数据结构格式。全球已有超过,种报文格式定义和,个.proto文件应用于RPC系统和持久化存储。它的优势在于结构化数据的序列化与跨语言、平台的兼容性,适用于即时通讯和数据存储等领域。 与XML和JSON相比,Protobuf体积更小,解析速度更快,特别适合像即时通讯这样对数据传输效率要求高的场景。它的核心特性体现在简化了服务端开发:服务端间通信只需关注接口方法(service)和参数(message),无需关注底层协议和字段解析,大大降低了开发成本。 在Proto3版本中,相较于Proto2,语法更为简洁,例如移除了"required"和"optional"等复杂的规则,强调约定而非语法。Proto3的repeated标量数值类型默认为packed编码,而Proto2默认非packed,同时增加了Go、Ruby、JavaNano等更多语言支持。 定义数据结构时,Protobuf提供一套基础数据类型,每个字段都有唯一编号,用于二进制标识。虽然编号范围广,但要避免使用~的预留区间。为了优化编码后的数据大小,高频率的字段建议使用1~范围的编号,但需留有扩展空间。 Proto3中repeated字段的规则有所变化,而Proto2中的可扩展字段规定有所不同。在编写消息类型时,可以在一个.proto文件中定义多个相关消息,方便扩展和组织。 添加注释支持C/C++风格,通过预留字段处理更新后的兼容性问题。默认值根据字段类型设定,如字符串、布尔值等。在枚举定义上,需确保第一个枚举值为0且无重复,除非启用别名选项。 使用.proto文件定义的数据结构需通过protoc编译器生成接口代码,以支持序列化和反序列化。然而,使用CMake的execute_process命令可能存在重新生成源码导致频繁编译的问题。 实例演示包括定义.proto文件、编写读写函数以及配置文件的使用,展示了如何在实际项目中应用Protocol Buffers。更多详细信息,请参考官方文档。2024-11-27 17:42
2024-11-27 16:38
2024-11-27 16:30
2024-11-27 15:59
2024-11-27 15:55
2024-11-27 15:51