關於protobuf的一些總結

2021-09-26 06:10:19 字數 2012 閱讀 9752

最近面試中被問protobuf的加解碼原理,非常的尷尬,因為我沒了解過,這裡稍作總結

proto檔案

每乙個proto檔案其實對應著我們正常的乙個模型(也就是model),只是proto檔案是用來描述這樣的乙個模型的檔案,並非實際上的工程model。

舉個例子,檔案person.proto:

message person
來看看這個檔案,proto使用message表示乙個訊息格式,類似於一般程式語言中的class,struct。

proto使用流程

這裡就不介紹使用方式了,簡單說一下proto檔案的使用流程,為下面講解編譯碼原理做一下鋪墊

編寫proto檔案

使用工具將proto檔案轉成對應語言的model檔案(person.proto->person.swift)

安裝google提供的三方庫protobuf

呼叫轉換出來的person.swift檔案中的encode和decode方法完成編譯碼等各類工作

protobuf編譯碼

接下來講一下重點的內容

protobuf中整型資料的編碼

protobuf中採用varints編碼對整型資料進行編碼,經過varints編碼後的資料,它的每乙個位元組的高位是乙個標記位。如果標記位是1,則代表下乙個位元組仍然是當前整型資料的組成;如果標記位是0,則代表當前資料結束了。

舉個例子:

->00000001  表示數字1,因為首位是標記為表示只需要當前位元組就能表示資料了,後七位就是這個值

->10101100 00000010 表示數字300,為什麼,首先看兩個位元組的最高位,1和0,1表示該下乙個位元組還是屬於這個數字的一部分,0表示這個資料到此子節表示結束,因此真實的資料是0101100 0000010 由於採用的是小端序,所以實際計算位0000010 0101100為 256+32+8+4 = 300

還有負數編碼,因為負數採用補碼,比如-1,表示成11111111,會導致每次數值都需要位元組拉滿才能表示的了(用variant編碼),所以對於負數protobuf採用zigzag編碼公式編碼以後再使用varint編碼。

protobuf整體的編碼

protobuf的訊息是經過編碼序列化的一系列key-value對,乙個型別的資料對應乙個key-value。value就是原始資料經過編碼後的資料,而key由field number和wire type組成。其中field number是指.proto檔案中定義的資料變數的field值(也就是前面proto格式中的1和2)。wire type用於區分字段值的型別(用於區分string,int32)

即:wire_type

type

0int32、int64、uint32、uint64、sint32、sint64、bool、enum

1fixed、sfixed64、double

2string、bytes、embedded、messages、packed repeated fields

舉個例子:

key = (field_number << 3) | wire_type

比如00001000,後三位表示wiretype = 0,前五位使用varint編碼,因此field number為1,也就是id這個字段

如果我們給id設定乙個值150,那麼對應的編碼就是

08 96 01

-> 00001000 10010110 00000001

-> wiretype = 0,field number為1即字段為id以及 0000001 0010110 = 128+16+4+2 =150

protobuf中字串的編碼

字串本身使用utf8編碼,整個字串字段使用key-len-value形式儲存,

protobuf中巢狀訊息的編碼

類似於字串,採用key-len-value來儲存,len表示該欄位對應的訊息所需要的訊息長度

歸總相對來說protobuf跟json的編碼完全不同,乙個編碼到字元,乙個編碼到位元組,因此速度和資料量上有乙個質的飛躍

開發protobuf擴充套件的一些筆記

乙個需求要接入公司內部的乙個基於protobuf協議的介面,protobuf的庫檔案都是proto編譯器生成的cpp檔案。要編譯成php擴充套件的話,需要c c 混編,這裡記錄一下。1 公升級一下安裝的protobuf,貌似c1的機器上的protobuf都是2.4.0的,當編譯高階的一些語法的pro...

關於stringstream的一些總結

c 標準庫中的提供了比ansi c的更高階的一些功能,即單純性 型別安全和可擴充套件性。可以使用這些庫來實現安全和自動的型別轉換。如果你已習慣了風格的轉換,也許你首先會問 為什麼要花額外的精力來學習基於的型別轉換呢?也許對下面乙個簡單的例子的回顧能夠說服你。假設你想用sprintf 函式將乙個變數從...

關於JSON的一些總結

一 關於json json是一種類似於xml的通用資料交換格式,具有比xml更高的傳輸效率.從結構上看,所有的資料 data 最終都可以分解成三種型別 第一種型別是標量 scalar 也就是乙個單獨的字串 string 或數字 numbers 比如 北京 這個單獨的詞。第二種型別是序列 sequen...