国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Google Protobuf 編解碼

Eric / 880人閱讀

摘要:優點在谷歌內部長期使用產品成熟度高跨語言支持多種語言包括和編碼后的消息更小更加有利于存儲和傳輸編解碼的性能非常高支持不同協議版本的前向兼容支持定義可選和必選字段的入門是一個靈活高效結構化的數據序列化框架相比與等傳統的序列化工具它更小更快更簡

Google Protobuf 優點:

在谷歌內部長期使用, 產品成熟度高.

跨語言、支持多種語言, 包括 C++、Java 和 Python.

編碼后的消息更小, 更加有利于存儲和傳輸.

編解碼的性能非常高.

支持不同協議版本的前向兼容.

支持定義可選和必選字段.

Protobuf 的入門

Protobuf 是一個靈活、高效、結構化的數據序列化框架, 相比與 xml 等傳統的序列化工具, 它更小、更快、更簡單.

Protobuf 支持數據結構化一次可以到處使用, 甚至跨語言使用, 通過代碼生成工具可以自動生成不同語言版本的源代碼, 甚至可以在使用不同版本的數據結構進程間進行數據傳遞, 實現數據結構前向兼容.

定義消息類型
syntax = "proto3";

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

該文件的第一行指定使用 proto3 語法, 如果不寫的話表示 proto2.

分配字段編號

string query = 1; 1 就是字段編號, 字段號主要用來標識二進制格式字段的. 1 到 15 字段號占一個字節. 16 到 2047 字段號需要兩個字節.

我們將對象轉換為報文的時候, 是按照字段編號進行報文封裝的; 我們接收到數據之后框架會幫我們按照字段號進行賦值.

不能使用數字19000到19999, 因為它們是為 Google Protobuf 保留的.

字段類型對應
.proto Type Notes C++ Type Java Type
double double double
float float float
int32 使用可變長度編碼, 對負數編碼效率低下
如果您的字段可能有負值, 則使用sint32代替.
int32 int
int64 使用可變長度編碼, 對負數編碼效率低下
如果您的字段可能有負值, 則使用sint64代替.
int64 long
uint32 使用可變長度編碼 uint32 int
uint64 使用可變長度編碼 uint64 long
sint32 使用可變長度編碼
有符號的int值這些編碼比常規int32更有效地編碼負數
uint32 int
sint64 使用可變長度編碼
有符號的int值這些編碼比常規int64更有效地編碼負數
int64 long
fixed32 四個字節, 如果值通常大于2的28次方, 則比uint32更有效 uint32 int
fixed64 四個字節, 如果值通常大于2的56次方, 則比uint64更有效 uint64 long
sfixed32 四個字節 int32 int
sfixed64 四個字節 int64 long
bool bool boolean
string 字符串必須始終包含UTF-8編碼或7位ASCII文本 string String
bytes 字符串必須始終包含UTF-8編碼或7位ASCII文本 string ByteString
默認值

對于字符串, 默認值是空字符串.

對于字節, 默認值為空字節.

對于bool, 默認值為false.

對于數字類型, 默認值為零.

對于枚舉, 默認值是第一個定義的枚舉值, 必須為0.

還請注意, 如果消息字段設置為默認值, 則該值將不會序列化.
允許嵌套

Protocol Buffers 定義 message 允許嵌套組合成更加復雜的消息

message SearchResponse {
  repeated Result results = 1;
}

message Result {
  string url = 1;
  string title = 2;
  repeated string snippets = 3;
}

更多的例子:

message SearchResponse {
  message Result {
    string url = 1;
    string title = 2;
    repeated string snippets = 3;
  }
  repeated Result results = 1;
}

message SomeOtherMessage {
  SearchResponse.Result result = 1;
}
message Outer {                  // Level 0
  message MiddleAA {  // Level 1
    message Inner {   // Level 2
      int64 ival = 1;
      bool  booly = 2;
    }
  }
  message MiddleBB {  // Level 1
    message Inner {   // Level 2
      int32 ival = 1;
      bool  booly = 2;
    }
  }
}
導入定義

可以在文件的頂部添加一個import語句:

import "myproject/other_protos.proto";
未知字段

未知字段就是解析器無法識別的字段. 例如, 當服務端使用新消息發送數據, 客戶端使用舊消息解析數據, 那么這些新字段將成為舊消息中的未知字段.

在3.5和更高版本中, 未知字段在解析過程中被保留, 并包含在序列化中輸出.

Map 類型

repeated 類型可以用來表示數組, Map 類型則可以用來表示字典.

map map_field = N;

map projects = 3;

key_type 可以是任何 int 或者 string 類型(任何的標量類型, 具體可以見上面標量類型對應表格, 但是要除去 floatdoublebytes)

枚舉值也不能作為 key.

key_type 可以是除去 map 以外的任何類型.

需要特別注意的是:

map 是不能用 repeated 修飾的.

map 迭代順序的是不確定的, 所以你不能確定 map 是一個有序的.

.proto 生成文本格式時, map 按 key 排序. 數字的 key 按數字排序.

從數組中解析或合并時, 如果有重復的 key, 則使用所看到的最后一個 key(覆蓋原則).從文本格式解析映射時, 如果有重復的 key, 解析可能會失敗.

Protocol Buffer 雖然不支持 map 類型的數組, 但是可以轉換一下, 用以下思路實現 maps 數組:

message MapFieldEntry {
  key_type key = 1;
  value_type value = 2;
}

repeated MapFieldEntry map_field = N;

上述寫法和 map 數組是完全等價的,所以用 repeated 巧妙的實現了 maps 數組的需求.

Protocol Buffer 命名規范

message 采用駝峰命名法. message 首字母大寫開頭. 字段名采用下劃線分隔法命名.

message SongServerRequest {
  required string song_name = 1;
}

枚舉類型采用駝峰命名法. 枚舉類型首字母大寫開頭. 每個枚舉值全部大寫, 并且采用下劃線分隔法命名.

enum Foo {
  FIRST_VALUE = 0;
  SECOND_VALUE = 1;
}

每個枚舉值用分號結束, 不是逗號.

服務名和方法名都采用駝峰命名法. 并且首字母都大寫開頭.

service FooService {
  rpc GetSomething(FooRequest) returns (FooResponse);
}
常用方法

getDefaultInstance(): 返回單例實例, 它與 newBuilder().build() 實例相同
getDescriptor(): 返回類型的描述符. 包括具有哪些字段以及類型. 這可以與 Message 的反射方法一起使用, 例如getField().
parseFrom(...): 返回反序列化后的 Message. 注意不會拋出 UninitializedMessageExceptionInvalidProtocolBufferException 異常.
Message.Builder: 中的 mergeFrom() 放會將數據解析為此類型的消息, 并進行消息合并.
newBuilder(): 創建一個新的構建器.

Any

Any類型允許包裝任意的message類型:

import "google/protobuf/any.proto";

message Response {
    google.protobuf.Any data = 1;
}
總結
message SubscribeReq {
  int32 subReqID = 1;
  string userName = 2;
  string productName = 3;
  string address = 4;
}

可以通過 pack()unpack()(方法名在不同的語言中可能不同)方法裝箱/拆箱,以下是Java的例子:

People people = People.newBuilder().setName("proto").setAge(1).build();
// protoc編譯后生成的message類
Response r = Response.newBuilder().setData(Any.pack(people)).build();
// 使用Response包裝people

System.out.println(r.getData().getTypeUrl());
// type.googleapis.com/example.protobuf.people.People
System.out.println(r.getData().unpack(People.class).getName());
// proto
Oneof

如果你有一些字段同時最多只有一個能被設置, 可以使用 oneof 關鍵字來實現, 任何一個字段被設置, 其它字段會自動被清空(被設為默認值):

message SampleMessage {
  oneof test_oneof {
    string name = 4;
    SubMessage sub_message = 9;
  }
}
默認值

比如我們創建了上面的消息類型, 我們在代碼中設置 builder.setSubReqID(0); 為 0, 零是數值類型的默認值; 所以我們會看到序列化后的數據中, 沒有對此字段進行序列化.

byte[] arry = builder.build().toByteArray();

arry 長度為 0. 對于字段類型是 string 類型的也是一樣的; 也就是說顯示賦值默認值也不會對其進行序列化.

保留字段
message SubscribeReq {
  
  reserved 2;
  
  int32 subReqID = 1;
  string userName = 2;
  string productName = 3;
  string address = 4;
}

顧名思義, 就是此字段會被保留可能在以后會使用此字段. 使用關鍵字 reserved 表示我要保留字段數 2.

上面代碼我們在生成 Java 文件的時候會出現 ubscribeReqPeoro.proto: Field "userName" uses reserved number 2 錯誤信息, 所以我們需要將 string userName = 2; 注釋, 或者刪除.

保留后我們無法對其設置或序列化和反序列化.

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/72796.html

相關文章

  • 解碼技術

    摘要:基于提供的對象輸入輸出流和可以直接把對象作為可存儲的字節數組寫入文件也可以傳輸到網絡上序列化的目的主要有兩個網絡傳輸對象持久化當進行遠程跨進程服務調用時需要把被傳輸的對象編碼為字節數組或者對象而當遠程服務讀取到對象或字節數組時需要將其解碼為 基于 Java 提供的對象輸入/輸出流 ObjectInputStream 和 ObjectOutputStream, 可以直接把 Java 對象...

    fobnn 評論0 收藏0
  • Netty(三) 什么是 TCP 拆、粘包?如何解決?

    摘要:是一個面向字節流的協議,它是性質是流式的,所以它并沒有分段。可基于分隔符解決。編解碼的主要目的就是為了可以編碼成字節流用于在網絡中傳輸持久化存儲。 showImg(https://segmentfault.com/img/remote/1460000015895049); 前言 記得前段時間我們生產上的一個網關出現了故障。 這個網關邏輯非常簡單,就是接收客戶端的請求然后解析報文最后發送...

    YanceyOfficial 評論0 收藏0
  • RPC框架原理及從零實現系列博客(一):思路篇

    摘要:等之所以支持跨語言,是因為他們自己定義了一套結構化數據存儲格式,如的,用于編解碼對象,作為各個語言通信的中間協議。 前段時間覺得自己一直用別人的框架,站在巨人的肩膀上,也該自己造造輪子了 一時興起 就著手寫起了RPC框架 這里寫了系列博客拿給大家分享下 這篇是開篇的思路篇 項目最終的代碼放在了我的github上https://github.com/wephone/Me... 歡迎sta...

    tracy 評論0 收藏0
  • netty 基于 protobuf 協議 實現 websocket 版本的簡易客服系統

    摘要:結構作為服務端作為序列化數據的協議前端通訊演示地址服務端實現啟動類長連接示例主線程組從線程組請求的解碼和編碼把多個消息轉換為一個單一的或是,原因是解碼器會在每個消息中生成多個消息對象主要用于處理大數據流,比如一個大小的文件如果你直接傳輸肯定 結構 netty 作為服務端 protobuf 作為序列化數據的協議 websocket 前端通訊 演示 GitHub 地址 showImg(...

    wua_wua2012 評論0 收藏0
  • netty 基于 protobuf 協議 實現 websocket 版本的簡易客服系統

    摘要:結構作為服務端作為序列化數據的協議前端通訊演示地址服務端實現啟動類長連接示例主線程組從線程組請求的解碼和編碼把多個消息轉換為一個單一的或是,原因是解碼器會在每個消息中生成多個消息對象主要用于處理大數據流,比如一個大小的文件如果你直接傳輸肯定 結構 netty 作為服務端 protobuf 作為序列化數據的協議 websocket 前端通訊 演示 GitHub 地址 showImg(...

    Shihira 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<