译 protocol buffers简单介绍

翻译自:https://developers.google.com/protocol-buffers/docs/overview

 

Protocol buffers是什么?

 

Protocol buffers是一款灵活、高效、自动化的数据描述语言。类似于XML能够将结构化数据序列化,但比XML更小,更快,更简单。通过它,你可以定义你的数据的结构,并生成基于各种语言的代码。这些你定义的数据流可以轻松地再传递并不破坏你已有的程序。并且你也可以更新这些数据而现有的程序也不会受到任何的影响。

 

Protocol buffers是怎样工作的?

 

通过定义一些数据和结构放在一个 .proto 文件之中。每一个protocol buffer 消息都是一小段结构,包含了一些名字。下面是一个.proto 文件内容的样例。

 

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


就像你看到的,这个消息的格式是十分简单的——对于每个消息类型都有一个或多个独特的数字字段,每一个字段都有一个名称和类型,可以是数字(整型或浮点),布尔,字符,原始字节,又或者是其它的protocol buffer消息类型,例如你自定义分层的数据结构。你还可以定义可选的required和repeated字段。你可以在这里Protocol Buffer Language Guide.找到更多编写.proto文件的信息。

在定义好了.proto文件,就可以将该文件作为protocol buffers编译器的输入文件,编译产生特定语言的数据定义代码文件了。编译器提供了简单的访问方法为每个字段(如name()和set_name())序列化/解析整个结构到原始字节——那么,举个栗子,如果你用的是C++,用这个编译器运行上面的例子会产生一个叫Person的类。你可以在你的应用中运用这个Person protocol buffer消息。你或许需要写一些像这些的代码:

 

  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);


然后,你可以像这样读取你的消息:

 

  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;


你可以增加一些新字段到你的消息格式中,这样并不会影响向后兼容;旧的二进制文件解析时会简单地忽略新的字段。所以如果你有通讯的协议是用到protocol buffers当作数据格式的话,你不用担心扩展你的协议会影响到原有的代码。

你可以在这里API Reference section找到关于使用生成protocol buffer的完整事例,你也可以在这里Protocol Buffer Encoding找到更多内容关于protocol buffer消息是怎样编码的。

 

为什么不使用XML?

同XML相比,Protocol buffers在序列化结构化数据方面有许多优点:
1. 更简单
2. 数据描述文件只需原来的1/10至1/3
3. 解析速度是原来的20倍至100倍
4. 减少了二义性
5. 生成了更容易在编程中使用的数据访问类

 

举个栗子,如果你想写一个带有name和email的person。在XML里,你需要这样写:

 

  1.  
    <person>
  2.  
    <name>John Doe</name>
  3.  
    <email>jdoe@example.com</email>
  4.  
    </person>


而相应的protocol buffer消息(应用protocol buffer文本格式)是:

 

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


当编码这段消息到protocol buffer二进制格式时(注释只是用来帮助人们调试和修改),它可能只有28字节和大约花费100到200纳秒的解释时间。但是如果用XML,它至少有69字节(如果你去掉空格)和花费5000到10000纳秒的解释时间。

而且,操作protocol buffer更加容易:

 

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

如果用XML,你不得不做这些事:

 

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


然而,protocol buffers不总是比XML好——例如,protocol buffers不是一个写基于文本的文档标记(例如HTML)的好方法,你不能轻易地交互结构和文本。还有,XML比较好看还好写,但protocol buffers,即使在原始格式下,也不是很好看,很好写。XML在某种程度上可以自描述。protocol buffer只在你有消息定义文件(.proto文件)时才有意义。

 

听起来好像挺适合我的!我要怎样开始?

 

先在这里Download the package下个包——这个包已经包含了各种语言(其实就只有Java,Pythin和C++)的protocol buffer编译器完整代码,当然,你还需要I/O和testing这些类。生成和安装你的编译器前,请看看README里的说明。

当你搞定一切的时候,你可以看看你所选择的语言的tutorial——这会帮你建立一个简单的用到protocol buffers的应用。

 

proto3介绍

 

我们最近做了一个新版本——Protocol Buffers language version 3(又叫做proto3),你可以在这里下载alpha release,我们加了一些新特性。我们简化了这个语言,现在可以用在更多的语言上了(C++,Python,JavaNano,Ruby,Objective-C和C#,不过有一些限制some limitations)。你还可以用在Go上,通过最新的Go protoc插件golang/protobuf。我们还在计划在更多的语言上用到protocol buffers。

还有一些内容和历史的问题就不翻译了。

posted @ 2018-08-23 19:04  _raindrop  阅读(145)  评论(0编辑  收藏  举报