字段名稱與字段類型
對(duì)于任何一個(gè)有用的信息都包含這樣幾部分:
- 字段名稱
- 字段類型
- 字段值
就像C/C++中定義變量時(shí):
int i = 100;
在這里,字段名稱就是i,字段類型是int,字段值是100。
剛才我們用varint以及ZigZag編碼解決了字段值表示的問題,那么該怎樣表示字段名稱和字段類型呢?
首先,對(duì)于字段類型還比較簡(jiǎn)單,因?yàn)樽侄晤愋途湍敲炊啵琾rotobuf中定義了6種字段類型:
對(duì)于6種字段類型我們使用3個(gè)比特位來表示就足夠了。
接下來比較有趣的是字段名稱該怎么表示呢?假設(shè)我們需要傳遞這樣一個(gè)字段:
int long_long_name = 100;
那么我們真的需要把“l(fā)ong_long_name”這么多字符通過網(wǎng)絡(luò)傳遞給對(duì)端嗎?
既然通信雙方需要協(xié)議,那么“l(fā)ong_long_name”這字段其實(shí)是client和server都知道的,它們唯一不知道的就是“ 哪些值屬于哪些字段 ”。
為解決這個(gè)問題, 我們給每個(gè)字段都進(jìn)行編號(hào) ,比如通信雙方都知道“l(fā)ong_long_name”這個(gè)字段的編號(hào)是2,那么對(duì)于:
int long_long_name = 100;
這個(gè)信息我們只需要傳遞:
- 字段名稱:2 (2對(duì)應(yīng)字段“l(fā)ong_long_name”)
- 字段類型:0 (0表示varint類型,參見上圖)
- 字段值:100
所以我們可以看到, 無論你用多么復(fù)雜的字段名稱也不會(huì)影響編碼后占據(jù)的空間,字段名稱根本就不會(huì)出現(xiàn)在編碼后的信息中, so clever。
從宏觀上看
我們已經(jīng)在protobuf中看到了數(shù)字以及字段名稱以及字段類型是怎么表示了,現(xiàn)在是時(shí)候從宏觀角度來看看多個(gè)字段該怎么編碼了。
從本質(zhì)上講,protobuf被編碼后形成一系列的key-value,每個(gè)key-value對(duì)應(yīng)一個(gè)proto中的字段。
也就是鍵值對(duì):
其中value比較簡(jiǎn)單,也就是字段值;而字段名稱和字段類型會(huì)被拼接成key,protobuf中共有6種類型,因此只需要3個(gè)比特位即可;字段名稱只需要存儲(chǔ)對(duì)應(yīng)的編號(hào),這樣可以就可以這樣編碼:
(字段編號(hào) << 3) | 字段類型
假設(shè)server接收到了一個(gè)key為0x08,其二進(jìn)制的表示為:
0000 1000
由于key也是利用varint編碼的,因此需要將第一個(gè)比特位去掉,這樣我的得到:
000 1000
根據(jù)key的編碼方式,其后三個(gè)比特位表示字段類型,即:
000
也就是0,這樣我們知道該key的類型是Varint(第0號(hào)類型),而字段編號(hào)為抹掉后3個(gè)比特位的值,即:
0001
這樣,我們就知道了該key對(duì)應(yīng)的字段編號(hào)為1,得到編號(hào)我們就能根據(jù)編號(hào)找到對(duì)應(yīng)的編號(hào)名稱。
嵌套數(shù)據(jù)
與Json和XML類似,protobuf中也支持嵌套消息,就像這樣:
message SubMsg {
optional int32 id = 1;
}
message Msg {
optional SubMsg msg = 1;
}
其實(shí)現(xiàn)也比較簡(jiǎn)單,這依然遵循被編碼后形成一系列的key-value,只不過對(duì)于嵌套類型的key來說,其value是由子消息的key-value組成。
protobuf與編譯語言
與Json一樣,protobuf也是一門語言,兼具了文本的可讀性以及二進(jìn)制的高效。
protobuf之所以能做到這一點(diǎn)就好比C語言與機(jī)器指令。
C語言是給程序員看的,可讀性好,而機(jī)器指令是給硬件使用的,性能好,編譯器會(huì)將C語言程序轉(zhuǎn)為機(jī)器可執(zhí)行的機(jī)器指令。
而protobuf也一樣,protobuf也是一門語言,會(huì)將可讀性較好的消息編碼為二進(jìn)制從而可以在網(wǎng)絡(luò)中進(jìn)行傳播,而對(duì)端也可以將其解碼回來。
在這里protobuf中定義的消息就好比C語言,編碼后的二進(jìn)制消息就好比機(jī)器指令。
而protobuf作為事實(shí)上語言必然有自己的語法,其語法就是這樣:
怎么樣,還覺得編譯原理沒什么用嗎?
不理解編譯原理是不可能發(fā)明protobuf這種技術(shù)的。
總結(jié)
我在寫這篇文章時(shí)不斷感嘆,Google的這項(xiàng)技術(shù)節(jié)省了多少程序員的時(shí)間,同時(shí)我們也能看到這種基石般的技術(shù)依賴的底層原理卻非常古老:
- 信息的編解碼
- 編譯原理
怎么樣,這些是不是遠(yuǎn)遠(yuǎn)沒有IT界各種流行的技術(shù)聽上去時(shí)髦有趣,而正是這種樸素的技術(shù)支撐起了工業(yè)界,現(xiàn)在你也應(yīng)該能明白底層技術(shù)的重要性了吧。
-
計(jì)算機(jī)
+關(guān)注
關(guān)注
19文章
7540瀏覽量
88649 -
Server
+關(guān)注
關(guān)注
0文章
93瀏覽量
24117 -
網(wǎng)絡(luò)編程
+關(guān)注
關(guān)注
0文章
72瀏覽量
10104
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
探討2對(duì)4二進(jìn)制解碼器及4到16二進(jìn)制解碼器配置
![探討2對(duì)4<b class='flag-5'>二進(jìn)制</b><b class='flag-5'>解碼</b>器及4到16<b class='flag-5'>二進(jìn)制</b><b class='flag-5'>解碼</b>器配置](https://file.elecfans.com/web1/M00/D8/0A/pIYBAF_qquOAL65sAAAXWexEff4436.png)
二進(jìn)制相對(duì)調(diào)相(二進(jìn)制差分調(diào)相2DPSK)的工作原理
![<b class='flag-5'>二進(jìn)制</b>相對(duì)調(diào)相(<b class='flag-5'>二進(jìn)制</b>差分調(diào)相2DPSK)的工作原理](https://file1.elecfans.com//web2/M00/A4/6C/wKgZomUMNCaAJPaQAADMOGqmdHg823.jpg)
二進(jìn)制
![<b class='flag-5'>二進(jìn)制</b>](https://file1.elecfans.com//web2/M00/A4/B5/wKgZomUMNVyAdVirAAASM9n2nZE370.gif)
二進(jìn)制編碼和二進(jìn)制數(shù)據(jù)
什么是二進(jìn)制計(jì)數(shù)器,二進(jìn)制計(jì)數(shù)器原理是什么?
二進(jìn)制電平,什么是二進(jìn)制電平
二進(jìn)制加法程序【匯編版】
二進(jìn)制加法程序【C語言版】
基于軟件二進(jìn)制代碼重用技術(shù)綜述
![基于軟件<b class='flag-5'>二進(jìn)制</b>代碼重用<b class='flag-5'>技術(shù)</b>綜述](https://file.elecfans.com/web2/M00/49/84/poYBAGKhwMGAWtbUAAAaqIccT9o069.jpg)
二進(jìn)制數(shù)據(jù)壓縮算法
二進(jìn)制解碼器到底是什么
![<b class='flag-5'>二進(jìn)制</b><b class='flag-5'>解碼</b>器到底是什么](http://p2.itc.cn/q_70/images03/20201228/2f86cca955c64727979a3d2edb4119a4.png)
二進(jìn)制解碼器開源設(shè)計(jì)
![<b class='flag-5'>二進(jìn)制</b><b class='flag-5'>解碼</b>器開源設(shè)計(jì)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
評(píng)論