mqtt_simple例程 nrf9160做主控連接阿里云——( 三 )


文章插圖
由此我們可以確定整個報文的第一字節為0x10(為了書寫方便后續將不在寫0x這個十六進制的標號,將直接使用10標識) 。
2)第二字節(也有可能是第2到第3、或者2到4,或者2到5)為什么會有不同的選擇 , 這是由于在第一字節確定了本包報文是什么類型后 , 會在后續告訴對方后面的可變報頭和負載一共有多少字節,當后面只有120個字節時可以用一個字節就表示好,但是當有500,或者1000時就不是一個字節可以表示的長度了(二進制表示方式,不理解的這里可以自己百度) 。為什么會有500,或者1000的那么大的差別呢 , 這由于有些可選配置,如有需要可配置進去(然后再后面的可變報頭給對應的bit位寫1 , 表示我要使用改配置,那么服務端檢測到該標志就可以知道說原來你本次有這個可選配置 , 我會在檢測負載數據時進行檢測讀取的),然后就是如果你設置設備名字或者密碼等時給了一個很長的名字,那數據不就是增加了,所以才在這把長度搞成這樣的可??,染忬还经过特殊导{柚萌媒郵丈璞縛梢院芎玫鬧辣敬偽ㄎ惱獠糠值降褪怯眉父鱟紙詒硎競竺媸蕕某ざ?,接下來我們會詳細講解一下,先把截圖放在下面 , 這就是為什么剩余長度bute2...有三個點的原因:

mqtt_simple例程 nrf9160做主控連接阿里云——

文章插圖

mqtt_simple例程 nrf9160做主控連接阿里云——

文章插圖
分別表示(每個字節的低 7 位用于編碼數據 ,  最高位是標志位) :1 個字節時(整個報文包的第2字節), 從 0(0x00)到 127(0x7f)2 個字節時(整個報文包的第2字節和第3字節) ,  從 128(0x80,0x01)到 16383(0Xff,0x7f)3 個字節時(整個報文包的第2、3、4字節),從 16384(0x80,0x80,0x01)到 2097151(0xFF,0xFF,0x7F)4 個字節時(整個報文包的第2、3、4、5字節) ,  從 2097152(0x80,0x80,0x80,0x01)到 268435455(0xFF,0xFF,0xFF,0x7F))
長度計算方式:
每個字節只取前面7位表示數據,第8位表示有沒有進位,如果第8位為1就表示有進位,長度還應該檢查第3字節的前前7位來乘128,因為2的7次方為128(這里不明白為什么是2的7次方可以百度),同理第3字節的第八為如果也是1,那么就應該檢查第4字節來加入計算,注意這里是乘于128*128,一直到第5字節:
eg1:假設我們現在有的可變報頭和負載一共有100(十進制)字節數據
100(十進制)的十六進制為0x64——所以我們該部分只有0x64即可
eg2:假設可變報頭和負載一共有500個數據(十進制)字節數據
500/128=3剩余116,那么116轉化為0x74,但是由于有進位所以第8位應該為1 , 所以原本的0x74(01110100)第8位變1(11110100)0xF4,所以第二字節為0xF4,那么由于有進位就有第三字節,所以第三字節為0x03 。
3)阿里云鏈接報文CONNECT的固定報頭確定有上面的講解,我們可以確定本次鏈接報文的固定報頭為(十六進制):
10 ?(問號的意思是現在還不知道我們本次可變報頭個負載數據長度,我們最后添加)
3.2.2、可變報頭在MQTT協議棧中規定可變報頭包含4個字段 , 分別為協議名(Protocol name)、協議級別(Protocol  Level) , 連接標志(Protocol  flags)、保持連接(Keep alive),下面我,來分別看一下 。
1)、協議名這一共6個字節,是協議直接規定的,我們直接帶入就行,每一字節數據如下:
 說明76543210byte1長度MSB(0)00000000byte2長度LSB(4)00000100byte3“M”01001101byte4“Q”01010001byte5“T”01010100byte6“T”01010100那根據協議規定我們可以得到如下的數據:
10 ?00 04 40 51 54 54
2)協議級別用一個字節表示協議級別 , 前面有說過我們使用和參考的協議為MQTT-V3.1.1 , 那么他的標識就是0x04,
mqtt_simple例程 nrf9160做主控連接阿里云——

文章插圖
3)連接標志用一個字節表示鏈接標志,其中每一位都有不同的意思,連接標志如圖標所示
mqtt_simple例程 nrf9160做主控連接阿里云——

文章插圖