MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基於發佈/訂閱(Publish/Subscribe)模式的輕量級通信協議,該協議構建於TCP/IP協議上,由IBM在1999年發佈,目前最新版本爲v3.1.1。MQTT最大的優勢在於能夠以極少的代碼和有限的帶寬,爲遠程設備提供實時可靠的消息服務。作爲一種低開銷、低帶寬佔用的即時通信協議,MQTT在物聯網、小型設備、移動應用等方面有普遍的應用。衆所周知,TCP/IP參考模型能夠分爲四層:應用層、傳輸層、網絡層、鏈路層。TCP和UDP位於傳輸層,應用層常見的協議有HTTP、FTP、SSH等。MQTT協議運行於TCP之上,屬於應用層協議,所以只要是支持TCP/IP協議棧的地方,均可以使用MQTT。服務器
一個使用MQTT協議的應用程序或者設備,它老是創建到服務器的網絡鏈接。客戶端能夠:
(1)發佈其餘客戶端可能會訂閱的信息; //發佈消息
(2)訂閱其它客戶端發佈的消息; //訂閱消息
(3)退訂或刪除應用程序的消息; //退訂消息
(4)斷開與服務器鏈接。 //斷開,鏈接服務器網絡
MQTT服務器以稱爲「消息代理」(Broker),能夠是一個應用程序或一臺設備。它是位於消息發佈者和訂閱者之間,它能夠:
(1)接受來自客戶的網絡鏈接; //接受客戶端鏈接
(2)接受客戶發佈的應用信息; //接收客戶端發佈的消息
(3)處理來自客戶端的訂閱和退訂請求; //處理消息的訂閱及退訂
(4)向訂閱的客戶轉發應用程序消息。 //推送消息session
每條MQTT命令消息的消息頭都包含一個固定的報頭,有些消息會攜帶一個可變報文頭和一個負荷。消息格式以下:ide
固定報文頭 | 可變報文頭 | 負荷ui
MQTT固定報文頭最少有兩個字節,第一字節包含消息類型(Message Type)和QoS級別等標誌位。第二字節開始是剩餘長度字段,該長度是後面的可變報文頭加消息負載的總長度,不包括用於編碼剩餘長度字段自己的字節數,該字段最多容許四個字節。
編碼
可變報文頭主要包含協議名、協議版本、鏈接標誌(Connect Flags)、心跳間隔時間(Keep Alive timer)、鏈接返回碼(Connect Return Code)、主題名(Topic Name)等,後面會針對主要部分進行講解。
加密
MQTT消息質量有三個等級,QoS 0,QoS 1和 QoS 2。
QoS 0:最多分發一次。消息的傳遞徹底依賴底層的TCP/IP網絡,協議裏沒有定義應答和重試,消息要麼只會到達服務端一次,要麼根本沒有到達。
QoS 1:至少分發一次。服務器的消息接收由PUBACK消息進行確認,若是通訊鏈路或發送設備異常,或者指定時間內沒有收到確認消息,發送端會重發這條在消息頭中設置了DUP位的消息。
QoS 2:只分發一次。這是最高級別的消息傳遞,消息丟失和重複都是不可接受的,使用這個服務質量等級會有額外的開銷。3d
在可變報文頭的鏈接標誌位字段(Connect Flags)裏有三個Will標誌位:Will Flag、Will QoS和Will Retain Flag,這些Will字段用於監控客戶端與服務器之間的鏈接情況。若是設置了Will Flag,就必須設置Will QoS和Will Retain標誌位,消息主體中也必須有Will Topic和Will Message字段。
那遺願消息是怎麼回事呢?服務器與客戶端通訊時,當遇到異常或客戶端心跳超時的狀況,MQTT服務器會替客戶端發佈一個Will消息。固然若是服務器收到來自客戶端的DISCONNECT消息,則不會觸發Will消息的發送。
所以,Will字段能夠應用於設備掉線後須要通知用戶的場景。代理
MQTT客戶端能夠設置一個心跳間隔時間(Keep Alive Timer),表示在每一個心跳間隔時間內發送一條消息。若是在這個時間週期內,沒有業務數據相關的消息,客戶端會發一個PINGREQ消息,相應的,服務器會返回一個PINGRESP消息進行確認。若是服務器在一個半(1.5)心跳間隔時間週期內沒有收到來自客戶端的消息,就會斷開與客戶端的鏈接。心跳間隔時間最大值大約能夠設置爲18個小時,0值意味着客戶端不斷開blog
Payload直譯爲負荷,可能讓人摸不着頭腦,實際上能夠理解爲消息主體(body)。
介紹MQTT協議的報文組成並經過wireshark抓取報文包分析報文內容
Connect報文在MQTT客戶端鏈接服務器時發出,報文由三部分組成,下面將分別介紹
Connect報文的可變報頭包含協議名,協議等級,鏈接標誌和保持鏈接
鏈接標誌包含用戶名標誌(username flag)、密碼標誌(password flag)、遺囑標誌(will flag)、遺囑服務指令(will Qos)、遺囑保留標誌(will retain)、清除會話標誌(clean session)、保留位(reserved)。
用戶名標誌(username flag):若用戶名標誌被置爲1,有效載荷中必須包含用戶名字段。
密碼標誌(password flag):若密碼標誌被置爲1,有效載荷中必須包含密碼字段,當用戶標誌被置爲0時,密碼標誌必須被置0.。
遺囑標誌(will flag):若遺囑標誌被置1,遺囑服務指令(will Qos)與遺囑保留標誌(will retain)會被服務器用到,遺囑消息中必須包含will topic和will message。
遺囑服務指令(will Qos):若是遺囑標誌被設置爲0,遺囑QoS也必須設置爲0(0x00),若是遺囑標誌被設置爲1,遺囑QoS的值能夠等於0(0x00),1(0x01),2(0x02)。它的值不能等 於3。
遺囑保留標誌(will retain):若遺囑保留標誌位被置位,服務器將保留遺囑消息(保留髮布),當客戶端異常斷開鏈接時將遺囑發給訂閱遺囑主題的客戶。
清除會話標誌(clean session):標誌被設置爲1,客戶端和服務端必須丟棄以前的任何會話並開始一個新的會話(以前的訂閱與發佈消息被刪除),若標誌爲0,恢復與服務器會話鏈接,若沒有鏈接 新建一個會話鏈接(不刪除以前與客戶端的會話信息並保存斷開本次會話以後的Qos1與Qos2消息)。
保留位(reserved):若是不爲0必須斷開客 戶端鏈接。
報文最後兩字節爲發送心跳包的間隔時間,當客戶端沒有數據發給服務器時,鬚髮送心跳包(pingreq)到服務器,保證鏈接不斷開。
CONNECT報文的有效載荷(payload)包含一個或多個以長度爲前綴的字段,可變報頭中的 標誌決定是否包含這些字段。若是包含的話,必須按這個順序出現:客戶端標識符,遺囑主題,遺囑消息,用戶名,密碼。
客戶端標識符(client identifier):服務器經過識別客戶標識符,肯定客戶端,識別二者間的MQTT會話相關狀態,服務器容許客戶端提供一個零字節的標識符,但clean session必須置1。
Connack爲服務器確認客戶端連上服務給出的迴應。
發佈消息可由客戶端或服務器發出,被消息訂閱者接收。
可變報頭按順序包含主題名和報文標識符。
若Qos爲0,無響應,若Qos爲1,返回PUBACK報文,若Qos爲2,返回PUBREC報文。
由服務器或客戶端確認已接收到pub消息
只有兩字節的報文標識(報文標識爲pub報文標識)
只有兩字節的報文標識(報文標識爲pub報文標識)
只有兩字節的報文標識(報文標識爲pub報文標識)
只有兩字節的報文標識(報文標識爲pub報文標識)
客戶端經過訂閱消息的方式來接收服務端下發的消息
SUBSCRIBE控制固定報頭的第3,2,1,0位是保留位,必須分別設置爲0,0,1,0。服務端必須將其它的任何值都當作是不合法的並關閉網絡鏈接
只有兩字節的報文標識
SUBACK報文包含一個返回碼清單,它們指定了SUBSCRIBE請求的每一個訂閱被授予的最大QoS等級。
只有兩字節的報文標識
只有兩字節的報文標識
包含須要取消訂閱的主題過濾器的列表.
只有兩字節的報文標識(報文標識爲unsub報文標識)
客戶端發送PINGREQ報文給服務端的。用於:
1.在沒有任何其它控制報文從客戶端發給服務的時,告知服務端客戶端還活着。
2.請求服務端發送 響應確認它還活着。
3.使用網絡以確認網絡鏈接沒有斷開
抓包注意:用標準不加密MQTT能抓到便於查看的報文,加密報文解析時不便於理解
創做不易,白嫖很差,各位的支持和承認,就是我創做的最大動力,咱們下篇文章見!
清風 | 文 【原創】
若是本篇博客有任何錯誤,請批評指教,不勝感激 !