日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Protobuf协议格式详解

發布時間:2023/12/18 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Protobuf协议格式详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

protobuf 是google開源的一個序列化框架,類似xml,json,最大的特點是基于二進制,比傳統的XML表示同樣一段內容要短小得多。還可以定義一些可選字段,用于服務端與客戶端通信。前面幾篇文章說了protobuf的用法,看到網上也沒有分析protobuf協議的文章,就利用一些時間寫了?protobuf 的協議分析,希望大家喜歡。

protobuf協議核心思想

基于128bits的數值存儲方式(Base 128 Varints)

數據表示方式:每塊數據由接連的若干個字節表示(小的數據用1個字節就可以表示),每個字節最高位標識本塊數據是否結束(1:未結束,0:結束),低7位表示數據內容。(可以看出數據封包后體積至少增大14.2%)

數字1的表示方法為:0000 0001,這個容易理解

數字300的表示方法為:1010 1100 0000 0010

protobuf字節序是小端字節序,所以這個數字實際是0000 0010 1010 1100

1010 1100 0000 0010→ 010 1100 ?000 0010
如下:000 0010 ?010 1100→ ?000 0010 ++ 010 1100→ ?10 0101100→ ?256 + 32 + 8 + 4 = 300


基于序號的協議字段映射(類似key-value結構)

所以字段可以亂序,可缺段(記optional)

message person{? ? required string name ? ? ?= 1;? ? required string country ?= 2;? ? optional int32 age ? ? ? ? ? = 3;}

效果相當于json數據:person?= [{1: "john"}, {2: ?"USA"}, {3: 30}],其中{3: 30} 還可以不傳,person還可以傳成 [{2: ?"USA"}, {1: "john"}],對端仍舊可以正常解析。


基于無符號數的帶符號數表示(ZigZag 編碼)

原始的帶符號數ZigZag編碼后的表示
00
-11
12
-23
21474836474294967294
-21474836484294967295
使用 zigzag 編碼,充分利用基于128bits的數值存儲(Base 128 Varints)的 技術,只需要加多1個位來表示符號。當絕對值小的數字非常有利,這種方式可以有效減少協議內容長度。

sint32類型編碼如下:(n << 1) ^ (n >> 31)
sint64類型編碼如下:(n << 1) ^ (n >> 63)?

協議數據結構

protobuf怎么在一長串二進制中表示若干個數據

做法就是每塊數據前加一個數據頭,表示數據類型及協議字段序號。

msg1_head + msg1 + msg2_head + msg2 + ...

數據頭也是基于128bits的數值存儲方式,一般1個字節就可以表示:

message Test1 {? ? required int32 a =?1;}
如上創建了 Test1 的結構并且把 a 設為 2,序列化好的二進制數據為:
0000 1000?0000 0010

以上數據轉成十六進制也就是 08 02,其中 8 是怎么得到的?

000 1000
低3位表示數據類型:0,其他表示協議字段序號:1,加上最高位0, 結果就是8

數據類型的表示如下:

類型含義用于哪些數據類型
0Varintint32, int64, uint32, uint64, sint32, sint64, bool, enum
164-bitfixed64, sfixed64, double
2Length-delimitedstring, bytes, embedded messages, packed repeated fields
3Start groupgroups (deprecated)
4End groupgroups (deprecated)
532-bitfixed32, sfixed32, float


寫在最后

protobuf的優缺點

優點前面也提到了,主要有兩個:

1、序列化和反序列化效率比 xml 和 json 都高(這個protobuf 自己做了測試,鏈接要翻墻);

2、字段可以亂序,欠缺,因此可以用來兼容舊的協議,或者是減少協議數據。


但是字段允許亂序欠缺,反過來也是缺點。所以這里總結?protobuf?兩個缺點,一個跟這有關:

1、如果字段過多,或者嵌套過深,都會影響反序列化效率,解析每一塊數據都要根據序號找到對應的位置然后再插入到已解析好的數據中。

2、數據基于128bits的存儲方式,單塊數據比較大時效率很受影響。解析數據需要取到所有字節的低7位,然后再拼成一整塊數據。

以上兩個缺點,特別是對于erlang這類沒有指針的語言來說,代價就相當昂貴。

3、協議序號也要占空間,序號越大占空間越大,當序號小于16時無需額外增加字節就可以表示。

protobuf 分析題

最后貼一道分析題,如果看得懂,基本就了解 protobuf 的協議內容了

message Test2 {? ? required int32 a = 3;}創建了Test2結構,a 賦值 150, 結果是0001 1000 1001 0110 ?0000 0001這個數寫成十進制就是 24 150 1,怎么得到這個數據?

總結

以上是生活随笔為你收集整理的Protobuf协议格式详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。