protobuf中文教程(第一篇)

摘要:
下一篇博文将描述。proto文件更详细。一旦定义了消息,就可以使用协议缓冲区提供的编译器进行编译。proto文件,根据您的语言生成数据访问类。

一、什么是protocol buffers

      Protocol buffers是一个灵活的、高效的、自动化的用于对结构化数据进行序列化的协议,与XML相比,Protocol buffers序列化后的码流更小、速度更快、操作更简单。你只需要将要被序列化的数据结构定义一次(译注:使用.proto文件定义),便可以使用特别生成的源代码(译注:使用protobuf提供的生成工具)轻松的使用不同的数据流完成对这些结构数据的读写操作,即使你使用不同的语言(译注:protobuf的跨语言支持特性)。你甚至可以更新你的数据结构的定义(译注:就是更新.proto文件内容)而不会破坏依赖“老”格式编译出来的程序。

二、protocol buffers的工作流程

     首先,你需要通过在.proto文件中定义protocol buffer的message类型来指定你想要序列化的数据结构,每一个protocol buffer message是一个逻辑上的信息记录,它包含一系列的键值对。这里展示一个最基本的.ptoto文件的例子,它定义了一个包含Person信息的message:

复制代码
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的格式非常简单--每一个message类型都有一个或多个带有唯一编号的字段,每一个字段有一个字段名和一个字段类型,字段类型可以是数值类型(比如整形或浮点型)、booleans(布尔类型)、strings(字符串类型)、raw bytes、甚至(正如上面的例子)还可以是其他的protocol buffer message类型,这允许你可以分层次的组织你的数据结构。你可以单独指定每一个字段为optional fields(可选字段)、required fields(必须字段)、repeated fields(可重复字段)。下一篇博文将会对.proto文件进行更详细的描述。

    一旦定义了你的message,你就可以根据你所使用的语言(译注:如JAVA、C++、Python等)使用protocol buffer提供的编译工具编译.proto文件生成数据访问类。这些类为每一个字段都提供了简单的访问器(比如name()和set_name()),同时还提供了将整个结构化数据序列化为原始字节数据以及从原始字节数据反序列化为结构化数据的方法(译注:C++中称之为函数)。例如,如果你使用的语言是C++,运行编译器编译上述的例子将生成一个名为Person的类,在你的应用程序中你可以使用这个类来填充、序列化和反序列化Person protocol buffer messages。之后你可能会写下如下类似的代码(译注:序列化):

1 Person person;
2 person.set_name("John Doe");
3 person.set_id(1234);
4 person.set_email("jdoe@example.com");
5 fstream output("myfile", ios::out | ios::binary);
6 person.SerializeToOstream(&output);

      之后,你可以将你的message读回(译注:反序列化):

1 fstream input("myfile", ios::in | ios::binary);
2 Person person;
3 person.ParseFromIstream(&input);
4 cout << "Name: " << person.name() << endl;
5 cout << "E-mail: " << person.email() << endl;

     你可以向你的message中添加新的字段而不会破坏前向兼容性;在解析时旧的二进制文件会简单的忽略掉新字段,所以,如果你的通信协议中使用protocol buffers作为数据交换格式,那么你可以扩展你的协议而不用担心会打乱现有的代码。

三、为什么不使用XML?

    相对于XML,protocol buffers在序列化结构数据时拥有许多先进的特性:

    1、更简单

    2、序列化后字节占用空间比XML少3-10倍

    3、序列化的时间效率比XML快20-100倍

    4、具有更少的歧义性

    5、自动生成数据访问类方便应用程序的使用

    举个例子,如果你想描述一个具有name和email的person数据结构,在XML中,你需要这样做:

 <person>
    <name>John Doe</name>
    <email>jdoe@example.com</email>
 </person>

      然而,在protocol buffers的message中(protocol buffers的文本格式)你需要这样做:

# Textual representation of a protocol buffer.
# This is *not* the binary format used on the wire.
person {
  name: "John Doe"
  email: "jdoe@example.com"
}

      当这个message被编码成protocol buffer的二进制格式(上述的文本格式只是为了方便阅读、调试和编辑),它将可能占用28个字节长度并且仅需要100-200纳秒的解析时间。相比,XML版本的则至少需要占用69字节的空间(这是在移除XML中的空格、换行之后),同时,将耗费大约5000-10000纳秒的解析时间。

      除此之外,手动操作protocol buffer更为方便,例如如下C++代码:

1  cout << "Name: " << person.name() << endl;
2  cout << "E-mail: " << person.email() << endl;

      然而如果你使用XML,那么你将需要这样做:

1 cout << "Name: "<< person.getElementsByTagName("name")->item(0)->innerText()<< endl;
2 cout << "E-mail: "<< person.getElementsByTagName("email")->item(0)->innerText()<< endl;

       事物总有两面性,和XML相比protocol buffers并不总是更好的选择,例如,protocol buffers并不适合用来描述一个基于文本的标记型文档(比如HTML),因为你无法轻易的交错文本的结构。另外,XML具有很好的可读性和可编辑性;而protocol buffers,至少在它们的原生形式上并不具备这个特点。XML同时也是可扩展、自描述的。而一个protocol buffer只有在具有message 定义(在.proto文件中定义)时才会有意义。

四、如何开始使用protocol buffers?

    首先,可以在这里下载安装包或者源码包

    https://developers.google.com/protocol-buffers/docs/downloads#release-packages

    这包含了针对JAVA、Python和C++编译器的完整源码,同时包含了你所需要的I/O和测试类。为了完成编译和安装,请参照README文件。

    一旦你完成了编译和安装,那么就可以开始使用protocol buffers了,后续的博文将会对C++和JAVA语言的具体使用细节进行阐述。

五、proto3介绍

     我们最新的版本version 3 alpha release引进了一个新的语言版本--Protocol Buffers version 3 (称之为proto3),它在我们现存的语言版本(proto2)上引进了一些新特性。proto3简化了protocol buffer language,这使其可以更便于使用和支持更多的编程语言:我们现在的alpha release版本可以让你能产生JAVA、C++、Pthyon、JavaNano、Ruby、Objective-C和C#版本的protocol buffer code,不过可能有时会有一些局限性。另外,你可以使用最新的Go protoc插件来产生Go语言版本的proto3 code,这可以从golang/protobuf Github repository获取。

    我们现在只推荐你使用proto3:

    1、如果你想尝试在我们新支持的语言中使用protocol buffers

    2、如果你想尝试我们最新开源的RPC实现gRPC(目前仍处于alpha release版本),我们建议你为所有的gRPC 服务器和客户端都使用proto3以避免兼容性问题。

     注意两个版本的语言APIs并不是完全兼容的,为了避免给原来的用户造成不便,我们将会继续维护之前的那个版本(译注:proto2)。

 六、最后说一点历史

      Protocol buffers最初被Google开发用来作为处理索引服务器的request/response协议。在protocol buffers诞生之前,有一个需要手动编码/解码requests、responses的协议,这个协议支持一个数字版本号,这导致了一个非常丑陋的代码,如下所示:

复制代码
1 if (version == 3) {
2    ...
3  } else if (version > 4) {
4    if (version == 5) {
5      ...
6    }
7    ...
8  }
复制代码

     很显然的,格式化的协议也导致了复杂的新版本推出问题,因为开发人员必须确保所有服务器请求的发起者和实际的请求处理者之间都要理解新的协议。

     Protocol buffers就是用来解决这些问题的:

     1、可以很容易的插入新字段,中间的服务器可以简单的解析它而不需要了解所有字段。

     2、格式更具有自描述性,可以被不同的语言处理(比如JAVA、C++、Python等)。

     3、自动产生序列化和反序列化代码从而避免了手动解析。

     4、除了应用在具有短暂生命周期的RPC请求中,人们开始使用protocol buffers 作为一种便利的自描述格式来存储数据(比如在Bigtable中)。

     5、服务器的RPC接口开始被声明为协议文件的一部分,通过protocol 编译器产生stub类,该类可以被用户根据实际实现的服务器接口进行重写。

from:https://www.cnblogs.com/chenyangyao/p/5422044.html

免责声明:文章转载自《protobuf中文教程(第一篇)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Windows Server 2008 R2无法连接无线网络的解决方法自动生成并导出word文档下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SQL Server返回XML格式数据

直接看例子吧,假设一张users表,里面只有id和Pwd两个字段。 1,最简单的用法: select * from users for xml auto 得到结果如下: <users pwd="walker" /> <users pwd="1C3A0B25C3D1C909E2BCB9FE44C2F904" /> <us...

spark内存管理详解

Spark 作为一个基于内存的分布式计算引擎,其内存管理模块在整个系统中扮演着非常重要的角色。理解 Spark 内存管理的基本原理,有助于更好地开发 Spark 应用程序和进行性能调优。本文旨在梳理出 Spark 内存管理的脉络,抛砖引玉,引出读者对这个话题的深入探讨。本文中阐述的原理基于 Spark 2.1 版本,阅读本文需要读者有一定的 Spark 和...

POI转换word doc文件为(html,xml,txt)

在POI中还存在有针对于word doc文件进行格式转换的功能。我们可以将word的内容转换为对应的Html文件,也可以把它转换为底层用来描述doc文档的xml文件,还可以把它转换为底层用来描述doc文档的xml格式的text文件。这些格式转换都是通过AbstractWordConverter特定的子类来完成的。  1 转换为Html文件 将doc文档转换...

Django-rest-framework --- 总结

目录 drf回顾总结 drf基础知识点 1.drf框架安装 安装 drf框架规矩的封装风格 drf请求生命周期 2.接口 3.restful接口规范 4.基于restful规范的原生Django接口 主路由:url.py api组件的子路由:api/url.py 模型层:model.py 后台层:admin.py 数据库迁移 视图层:vi...

在lua环境中使用protobuf

最近在cocos2dx的项目中,需要在LUA脚本层使用protobuf协议。官方已经推出了很多种语言的版本。但唯独LUA版本不全。于是开始研究protobuf在LUA下的实现,将完整的过程记录了下来,希望对其它人能有所帮助。 1、下载protoc-gen-lua 可以通过HG从服务器(hg clonehttps://code.google.com/p/pr...

json常用的注解

json注解: 1、@jsonIgnoreProperties: 此注解是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。 写法将此标签加在model 类的类名上 ,可以多个属性也可以单个属性 //生成json时将name和age属性过滤 @JsonIgnoreProperties({"name"},{...