mysql協議分析1---報文的格式和基本型別
navicat 和 mysql 是一對好基友,每天都有非常頻繁的交流,主人在navicat上寫下每條sql語句,輕輕的點了下執行按鈕,navicat就飛快的把主人的指令傳送到mysql那裡,mysql立馬把返回結果傳回navicat那裡顯示給主人看。主人對他們的效率很滿意,同時主人也有點好奇:你們兩個基友是怎麼通訊的呢?如果不通過navicat,我用程式直接和mysql互動該怎麼做呢?
mysql 笑道:這是我們之間的祕密。。。
navicat有點不開心了:難道主人想拋棄我嗎?嗚嗚嗚。。。
主人安慰道:你想多了,我只是想更瞭解你們呀。
那我就給你詳細講講我們之間的小祕密吧,mysql悠悠的說道:
想要通過我的互動,就得照我規定的格式來,不能每個人過來都講自己的方言,我可聽不懂,來到我的地盤就得按我的規矩來。
1.我給你發的報文都是這種格式的:
伺服器--->客戶端的報文格式
前面3個位元組payload_length表示後面資料的實際長度,中間一個位元組sequence_id表示報文的序號,從0開始,每次加1,最後的paylaod就是我發你的內容啦。
你可能也發現了,payload_length用3個位元組表示,最大隻能表示 224−1 bytes也是16M,如果報文大於或者等於16M那就要拆成2個報文了哦,
比如剛好傳送16M的報文:
ff ff ff 00 (資料域16M)... 00 00 00 01 (資料域為空)
第二個報文的資料域是空的。
2.客戶端發給我的報文也是要按照一定格式的哦:
客戶端--->伺服器的報文格式
第一個位元組表示命令的型別
後面的位元組表示具體的命令,例如關閉連線的報文是長這樣子滴:
這樣規定好後,我們就有共同語言啦,就能聽得懂對方在講什麼了,所以說有共同語言是很重要滴。
主人細細的回味了下mysql剛才說的話,發現還有個地方沒弄明白問道:你發給我的報文中int<3>,string<var>表示什麼意思呀?
mysql忽然意識到還忘了說一件重要的事情:哎呦,我忘了和你說基本的資料型別了。
mysql有2種基本的資料型別:
Integers(整數型) 和 String(字串)
Integers(整數型)分為定長的整數型別(Fixed-length integers)和變長的整數型別(Length-encoded integers)
1.定長的整數型別(Fixed-length integers)分別能表示1,2,3,4,6,8位元組的長度:
int<1>表示佔1個位元組的長度, int<2>表示佔2個位元組的長度,以此類推,
比如 int<3> 表示1是這麼表示的:01 00 00
對了,mysql協議中位元組是按小頭(LittileEndian)的方式表示的,低位的位元組在前面,總體佔3個位元組,所以第一個位元組是01,後面是00 00
2.變長的整數型別(Length-encoded integers)
- 如果數字 < 251, 就用一個位元組表示 = 1個位元組
- 如果數字 ≥ 251 並且 < (216),就用
fc
+ 2個位元組表示 = 3個位元組
- 如果數字 ≥ (216) 並且 < (224),就用
fd
+ 3個位元組表示 = 4個位元組
- 如果數字 ≥ (224) 並且 < (264) ,就用
fe
+ 8個位元組表示 = 9個位元組
主人表示很奇怪:一個位元組最多能表示255個數,為什麼不能直接表示到255?而是隻表示到250?
mysql微微一笑道:因為251,252,253,254,255已經被我徵用了哦,它們表示特殊的用途:
251(fb):表示 NULL
252(fc):表示數值的大小佔後面的2個位元組
253(fd):表示數值的大小佔後面的3個位元組
254(fe):表示數值的大小佔後面的8個位元組
255(ff): 表示一個錯誤報文 ERR packet
下面說說String(字串)型別:
1.變長的字元型別(LengthEncodedString):和上面變長整數型別是一樣的,根據第一個位元組的值判斷所佔位元組的長度
2.
定長的字串型別(
FixedLengthString):後面的數字表示字串
所佔位元組的長度
3.動態的計算長度(VariableLengthString):
根據var
動態的計算長度
4.包末端字串方式(RestOfPacketString
):沒搞懂
5.
空結尾的字串型別
(NulTerminatedString):字串遇到 00 結束
原來如此,主人豁然開朗,看著navicat 和 mysql都親切了許多,知道他們之間是怎麼通話之後,一個邪惡的想法慢慢從心底升起,嘿嘿,那我不就可以監聽他們之間的對話了嘛,哈哈哈哈哈哈哈哈。。。
我的公眾號,歡迎關注