C++_程序员_Protocol_Buffers_基础指南

摘要: 这篇教程提供了一个面向 C++ 程序员关于 protocol buffers 的基础介绍。通过创建一个简单的示例应用程序,它将向我们展示: 在 .proto 文件中定义消息格式 使用 protocol buffer 编译器 使用 C++ protocol buffer API 读写消息 这不是一个关于在 C++ 中使用 protocol buffers 的全面指南。

这篇教程提供了一个面向 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

 
  1. package tutorial;
  2.  
  3. message Person {
  4. required string name = 1;
  5. required int32 id = 2;
  6. optional string email = 3;
  7.  
  8. enum PhoneType {
  9. MOBILE = 0;
  10. HOME = 1;
  11. WORK = 2;
  12. }
  13.  
  14. message PhoneNumber {
  15. required string number = 1;
  16. optional PhoneType type = 2 [default = HOME];
  17. }
  18.  
  19. repeated PhoneNumber phone = 4;
  20. }
  21.  
  22. message AddressBook {
  23. repeated Person person = 1;
  24. }

如你所见,其语法类似于 C++ 或 Java。我们开始看看文件的每一部分内容做了什么。

.proto 文件以一个 package 声明开始,这可以避免不同项目的命名冲突。在 C++,你生成的类会被置于与package 名字一样的命名空间。

下一步,你需要定义消息message。消息只是一个包含一系列类型字段的集合。大多标准的简单数据类型是可以作为字段类型的,包括 boolint32floatdouble 和 string。你也可以通过使用其他消息类型作为字段类型,将更多的数据结构添加到你的消息中——在以上的示例,Person 消息包含了 PhoneNumber 消息,同时AddressBook 消息包含 Person 消息。你甚至可以定义嵌套在其他消息内的消息类型——如你所见,PhoneNumber 类型定义于 Person 内部。如果你想要其中某一个字段的值是预定义值列表中的某个值,你也可以定义 enum 类型——这儿你可以指定一个电话号码是 MOBILEHOME 或 WORK 中的某一个。

每一个元素上的 = 1= 2 标记确定了用于二进制编码的唯一“标签”tag。标签数字 1-15 的编码比更大的数字少需要一个字节,因此作为一种优化,你可以将这些标签用于经常使用的元素或 repeated 元素,剩下 16 以及更高的标签用于非经常使用的元素或 optional 元素。每一个 repeated 字段的元素需要重新编码标签数字,因此 repeated 字段适合于使用这种优化手段。

每一个字段必须使用下面的修饰符加以标注:

转载于:https://my.oschina.net/u/3472227/blog/917024

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值