蚊章汇 - Google
type: channel
link: https://linuxcn.bwsl.wang/author/443/
description: Google
items: C++ 程序员 Protocol Buffers 基础指南

C++ 程序员 Protocol Buffers 基础指南
type: item
date: 2016-11-04T18:37:00+08:00
description: 这篇教程提供了一个面向 C++ 程序员关于 protocol buffers 的基础介绍。通过创建一个简单的示例应用程序，它将向我们展示：在 .proto 文件中定义消息格式使用 protocol buffer 编译器使用 C++ protocol buffer API 读写消息这不是一个关于在 C++ 中使用 protocol buffers 的全面指南。要获取更详细的信息，请参考 Protocol Buffer Language Guide 和 Encoding Reference。为什么使用 Protocol Buffers我们接下来要使用的例子是一个非常简单的"地址簿"应用程序，它能从文件中读取联系人详细信息。地址簿中的每一个人都有一个名字、ID、邮件地址和联系电话。如何序列化和获取结构化的数据？这里有几种解决方案：以二进制形式发送/接收原生的内存数据结构。通常，这是一种脆弱的方法，因为接收/读取代码必须基于完全相同的内存布局、大小端等环境进行编译。同时，当文件增加时，原始格式数据会随着与该格式相关的软件而迅速扩散，这将导致很难扩展文件格式。你可以创造一种 ad-hoc 方法，将数据项编码为一个字符串——比如将 4 个整数编码为 12:3:-23:67。虽然它需要编写一次性的编码和解码代码且解码需要耗费一点运行时成本，但这是一种简单灵活的方法。这最适合编码非常简单的数据。序列化数据为 XML。这种方法是非常吸引人的，因为 XML 是一种适合人阅读的格式，并且有为许多语言开发的库。如果你想与其他程序和项目共享数据，这可能是一种不错的选择。然而，众所周知，XML 是空间密集型的，且在编码和解码时，它对程序会造成巨大的性能损失。同时，使用 XML DOM 树被认为比操作一个类的简单字段更加复杂。Protocol buffers 是针对这个问题的一种灵活、高效、自动化的解决方案。使用 Protocol buffers，你需要写一个 .proto 说明，用于描述你所希望存储的数据结构。利用 .proto 文件，protocol buffer 编译器可以创建一个类，用于实现对高效的二进制格式的 protocol buffer 数据的自动化编码和解码。产生的类提供了构造 protocol buffer 的字段的 getters 和 setters，并且作为一个单元来处理读写 protocol buffer 的细节。重要的是，protocol buffer 格式支持格式的扩展，代码仍然可以读取以旧格式编码的数据。在哪可以找到示例代码示例代码被包含于源代码包，位于“examples”文件夹。可在这里下载代码。定义你的协议格式为了创建自己的地址簿应用程序，你需要从 .proto 开始。.proto 文件中的定义很简单：为你所需要序列化的每个数据结构添加一个 消息 （ message ） ，然后为消息中的每一个字段指定一个名字和类型。这里是定义你消息的 .proto 文件 addressbook.proto。package tutorial; message Person { required string name = 1; required int32 id = 2; optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; } message AddressBook { repeated Person person = 1; } 如你所见，其语法类似于 C++ 或 Java。我们开始看看文件的每一部分内容做了什么。.proto 文件以一个 package 声明开始，这可以避免不同项目的命名冲突。在 C++，你生成的类会被置于与 package 名字一样的命名空间。下一步，你需要定义 消息 （ message ） 。消息只是一个包含一系列类型字段的集合。大多标准的简单数据类型是可以作为字段类型的，包括 bool、int32、float、double 和 string。你也可以通过使用其他消息类型作为字段类型，将更多的数据结构添加到你的消息中——在以上的示例，Person 消息包含了 PhoneNumber 消息，同时 AddressBook 消息包含 Person 消息。你甚至可以定义嵌套在其他消息内的消息类型——如你所见，PhoneNumber 类型定义于 Person 内部。如果你…