zoukankan      html  css  js  c++  java
  • proto3 协议指引

    一、protocal buffer 是什么?

    一种序列化机制。

    什么是序列化?

    一种转化为可存储和传输对象的过程。

    序列化的方式有很多,那么proto有什么特殊的呢?

    它的英文介绍里提到了neutral这个词,中立,无关的。

    language-neutral 跨语言:它可以应用于多种开发语言之间数据交互。

    platform-neutral 跨平台:它可以运行于多种系统平台

    可扩展

    序列化过程性能优越,速度快

    序列化后为二进制数据,相对的占用空间更小(存储成本及传输成本)及一定程度的保障数据的安全性。

    提供支持多语言的自动化代码生成工具,开发易用性

    二、下面以一个简单地示例开始:

    proto3 文件:.proto 

    syntax = "proto3";
    
    message SearchRequest {
      string query = 1;
      int32 page_number = 2;
      int32 result_per_page = 3;
    }

    第一行声明当前使用的proto3版本协议语法(proto编译器默认使用proto2版本协议语法),声明必须为文件的第一行,此前不能有任何内容,包括注释。

    消息使用“message”关键字定义,内部以“字段类型 字段名称 = 字段序号;”形式定义所要包含额属性。

    1、序号:

    每一个字段被赋予一个唯一的序号,起始为1不可重复。通常考虑到向后兼容的因素,不建议修改已定义的字段序号。

    需要注意的是,序号大小会影响序列化编码的空间占用,例如:

    序号范围[1,15]:proto使用1个字节存储字段的序号及类型,适宜定义常用字段。

    序号范围 [16,2047]:proto使用2个字节存储字段的序号及类型。

    ...

    序号可用域[1,229 - 1],其中[19000,19999]为proto保留序号范围(编译使用),不可使用。另外,开发方可以约定保留序号,以供扩展或其它特殊使用。

    2、字段约束

    singular:更直观的可以用optional来释义,可选字段,0个或1个,proto3中未默认约束。

    repeated:列表集合字段类型,可以包含 >=0 个字段元素。 

    三、数据类型

    proto3编码类型对应不同开发语言数据类型:

    .proto Type说明Java Type
    double   double
    float   float
    int32

    使用可变长编码。

    对于负数编码效率较低(可以使用sint32类型存储)

    int
    int64

    使用可变长编码。

    对于负数编码效率较低(可以使用sint64类型存储)

    long
    uint32 使用可变长编码。 int[1]
    uint64 使用可变长编码。 long[1]
    sint32 使用可变长编码,存储有符号整数。尤其对负数编码效率更高。 int
    sint64

    使用可变长编码,存储有符号整数。尤其对负数编码效率更高。

    long
    fixed32 四字节空间占用。存储值>228时,存储效率高于uint32。 int[1]
    fixed64

    八字节空间占用。存储值>256时,存储效率高于uint64。

    long[1]
    sfixed32 四字节空间占用 int
    sfixed64 八字节空间占用 long
    bool   boolean
    string UTF-8编码或者7位ASCII文本,长度不可超过232 String
    bytes 可以存储任何二进制数据,长度不可超过232 ByteString

     

    四、默认值

    singular 类型字段在进行编解码时,如果没有进行赋值则赋予默认值。不同类型使用默认值如下:

    类型 默认值
    string 空字符串
    bytes 空byte数组
    bool false
    数值类型 0
    enums 定义的枚举第一个元素(默认必须为0)
    定义的message类型 不赋值
    repeated * 空列表

    proto3关于默认值的操作,在我们实际的使用中不免会造成一些困扰,我们需要去区分未知结果默认值结果两者之间的区别。例如,我们定义了bool类型字段updated(是否已更新),默认的false所表示未更新,则会将未知是否已更新覆盖。

    对于此,通常处理的方式是引入包装类型wrapper,使用如下:

    import "google/protobuf/wrappers.proto";

    wappers.proto文件定义如下:

    // Protocol Buffers - Google's data interchange format
    // Copyright 2008 Google Inc.  All rights reserved.
    // https://developers.google.com/protocol-buffers/
    //
    // Redistribution and use in source and binary forms, with or without
    // modification, are permitted provided that the following conditions are
    // met:
    //
    //     * Redistributions of source code must retain the above copyright
    // notice, this list of conditions and the following disclaimer.
    //     * Redistributions in binary form must reproduce the above
    // copyright notice, this list of conditions and the following disclaimer
    // in the documentation and/or other materials provided with the
    // distribution.
    //     * Neither the name of Google Inc. nor the names of its
    // contributors may be used to endorse or promote products derived from
    // this software without specific prior written permission.
    //
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    // Wrappers for primitive (non-message) types. These types are useful
    // for embedding primitives in the `google.protobuf.Any` type and for places
    // where we need to distinguish between the absence of a primitive
    // typed field and its default value.
    //
    // These wrappers have no meaningful use within repeated fields as they lack
    // the ability to detect presence on individual elements.
    // These wrappers have no meaningful use within a map or a oneof since
    // individual entries of a map or fields of a oneof can already detect presence.
    
    syntax = "proto3";
    
    package google.protobuf;
    
    option csharp_namespace = "Google.Protobuf.WellKnownTypes";
    option cc_enable_arenas = true;
    option go_package = "github.com/golang/protobuf/ptypes/wrappers";
    option java_package = "com.google.protobuf";
    option java_outer_classname = "WrappersProto";
    option java_multiple_files = true;
    option objc_class_prefix = "GPB";
    
    // Wrapper message for `double`.
    //
    // The JSON representation for `DoubleValue` is JSON number.
    message DoubleValue {
      // The double value.
      double value = 1;
    }
    
    // Wrapper message for `float`.
    //
    // The JSON representation for `FloatValue` is JSON number.
    message FloatValue {
      // The float value.
      float value = 1;
    }
    
    // Wrapper message for `int64`.
    //
    // The JSON representation for `Int64Value` is JSON string.
    message Int64Value {
      // The int64 value.
      int64 value = 1;
    }
    
    // Wrapper message for `uint64`.
    //
    // The JSON representation for `UInt64Value` is JSON string.
    message UInt64Value {
      // The uint64 value.
      uint64 value = 1;
    }
    
    // Wrapper message for `int32`.
    //
    // The JSON representation for `Int32Value` is JSON number.
    message Int32Value {
      // The int32 value.
      int32 value = 1;
    }
    
    // Wrapper message for `uint32`.
    //
    // The JSON representation for `UInt32Value` is JSON number.
    message UInt32Value {
      // The uint32 value.
      uint32 value = 1;
    }
    
    // Wrapper message for `bool`.
    //
    // The JSON representation for `BoolValue` is JSON `true` and `false`.
    message BoolValue {
      // The bool value.
      bool value = 1;
    }
    
    // Wrapper message for `string`.
    //
    // The JSON representation for `StringValue` is JSON string.
    message StringValue {
      // The string value.
      string value = 1;
    }
    
    // Wrapper message for `bytes`.
    //
    // The JSON representation for `BytesValue` is JSON string.
    message BytesValue {
      // The bytes value.
      bytes value = 1;
    }

    五、枚举

    enum 枚举对象 {

      UNKOWN = 0; //默认值机制使用(首先必须有一个枚举值为0的枚举实例,其次兼容proto2中使用第一个变量为默认值的机制)

      枚举实例 = 枚举值;

      ... ...

    }

    六、定义更新

    1、不可修改已定义的字段序号。

    2、可以删除已定义的字段,但是其序号不可在被使用。

    3、int32, uint32, int64, uint64及bool是相互兼容的,只不过转换过程会产生值域变更

    4、sint32 和 sint64 是相互兼容的。

    5、byte3存储值为有效UTF-8编码内容时与string相互兼容。

    七、未知字段

    未能对应解析的字段会存储于未知字段中。此机制在proto3中最初抛弃,v3.5版本重新引入。

    八、Map 类型

    定义如下:

    map<key_type, value_type> map_field = N。

    key_type:任何整形或者string类型。

    value_type:可以为除了Map类型外的任何类型。

     

    作者:WindWant
  • 相关阅读:
    tabbar 旋转指定的页面
    GDAL中文路径不能打开&Shp文件字段属性值中文乱码
    Project : error PRJ0019: 工具从"Moc'ing xxx.h..."
    详解Android中的屏幕方向
    qt中获取文件路径和文件名
    vs2005下Qt项目中修改exe图标的方法
    Qt & C/C++统计运行时间
    Qt 中Treewidget添加右键菜单
    QT 中文乱码解决方案
    Qt多线程应用QRunnable显示进度条示例
  • 原文地址:https://www.cnblogs.com/niejunlei/p/14398375.html
Copyright © 2011-2022 走看看