深入理解mqtt協議,mqtt測試

MQTT協議

MQTT是輕量級基於代理的發佈/訂閱的消息傳輸協議,它可以通過很少的代碼和帶寬和遠程設備連接。例如通過衛星和代理連接,通過撥號和醫療保健提供者連接,以及在一些自動化或小型設備上,而且由於小巧,省電,協議開銷小和能高效的向一和多個接收者傳遞信息,故同樣適用於稱動應用設備上

 

Mqtt協議特點

1.使用發佈/訂閱消息模式,提供一對多的消息發佈,解除應用程序耦合。

2.協議簡單,最小的頭部只需2個字節,特別適合於嵌入式中。

3.對負載內容屏蔽的消息傳輸。

4.使用 TCP/IP 提供網絡連接。

5.有三種消息發佈服務質量:

(1) “至多一次,消息發佈完全依賴底層 TCP/IP 網絡。會發生消息丟失或重複。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因爲不久後還會有第二次發送。

(2) “至少一次,確保消息到達,但消息重複可能會發生。

(3) “只有一次,確保消息到達一次。這一級別可用於如下情況,在計費系統中,消息重複或丟失會導致不正確的結果。

 

6. 使用 Last Will Testament 特性通知有關各方客戶端異常中斷的機制。

 

 

PUB/SUB 模型

 



 

Mqtt結構

固定頭部,使用兩個字節,共16位:

bit

7

6

5

4

3

2

1

0

byte 1

Message Type

DUP flag

QoS level

RETAIN

byte 2

Remaining Length

 

消息類型

使用4位二進制表示,可代表16種消息類型

Mnemonic

Enumeration

Description

Reserved

0

Reserved----保留待用

CONNECT

1

Client request to connect to Server----客戶端連接請求

CONNACK

2

Connect Acknowledgment----連接反饋

PUBLISH

3

Publish message-----發佈消息

PUBACK

4

Publish Acknowledgment-----發佈反饋

PUBREC

5

Publish Received (assured delivery part 1)----發佈消息被接收

PUBREL

6

Publish Release (assured delivery part 2)

PUBCOMP

7

Publish Complete (assured delivery part 3)----發佈消息完成

SUBSCRIBE

8

Client Subscribe request----客戶端訂閱

SUBACK

9

Subscribe Acknowledgment----訂閱反饋

UNSUBSCRIBE

10

Client Unsubscribe request----客戶端解除訂閱

UNSUBACK

11

Unsubscribe Acknowledgment----接觸訂閱反饋

PINGREQ

12

PING Request-------心跳檢測

PINGRESP

13

PING Response----心跳反饋

DISCONNECT

14

Client is Disconnecting----客戶端斷開連接

Reserved

15

Reserved----保留待用

 

 

消息類型使用的場景這裏我使用的是wireshark 抓包工具

 

首先我先來測試demo1也就是消息類型QOS

 

 

 

代碼中我沒有設置QOS類型所以他會默認選0

 

至多發送一次,發送即丟棄。沒有確認消息,也不知道對方是否收到

 



 

 

我本機ip192.168.101.248 192.168.56.3服務器發送訂閱請求如上圖mqtt使用的是TCP/IP網絡傳輸所以也要經過三次握手原則。在客戶機和服務器之間建立正常的TCP網絡連接時,客戶機首先發出一個SYN消息,服務器使用SYN+ACK應答表示接收到了這個消息,最後客戶機再以ACK消息響應。這樣在客戶機和服務器之間才能建立起可靠的TCP連接,數據纔可以在客戶機和服務器之間傳遞,也就是上面mqtt的特點:使用 TCP/IP 提供網絡連接。

 

 

名詞解釋:SYN表示建立連接, FIN表示關閉連接, ACK表示響應, PSH表示有DATA數據傳輸, RST表示連接重置。

 



 
Connect 中可以看到我的發佈者ID demo也就是我代碼中所寫的:



 

 

第二個Connect Ack 內容

 



 
可以看到是0;因爲我沒有設置QOS消息方法所以默認是00代表最多1次,發完就丟棄,不保證消息是否收到。下面可以參考QOS服務質量資料。

 

 

Publish message 也就是我們發送的消息了

 



 

因爲這裏漢字是採用8進製表示的,如果轉碼需要經過轉爲16進制每兩位代表一個漢字共四位,從中間的topic就可以看出那個就是我們發送的消息了。

 

 

 

PUBACK

 


 

服務器向我們返回的信息也就是這個信息的ID號了。

 

DISCONNECT

-客戶端斷開連接,因爲我在代碼中最後執行了斷開連接的方法所以會通知服務器。代碼如圖:

 

 

 

 

QOS 1

 

(所有QoS level 1都要在可變頭部中附加一個16位的消息ID提供SUBSCRIBE(訂閱)UNSUBSCRIBE(退訂)消息使用。針對消息的發佈,Qos level 1,意味着消息至少被傳輸一次。發送者若在一段時間內接收不到PUBACK消息,發送者需要打開DUB標記爲1,然後重新發送PUBLISH消息。因此會導致接收方可能會收到兩次PUBLISH消息)

 

因爲連接的是時候可以接受到mqtt服務器的回覆,在送出去消息的時候要讓服務器回執發送不到客戶端,這個測試環境不好測試所以就沒例子。

 

 

 

QOS 2

 

 

從上圖可以看出首先發佈者連接mqtt服務器,然後得到服務器的回覆,發佈者就開始發送消息,服務器這邊回覆 publish received也就是告訴發佈者你的消息我收到了,接着發佈告訴服務器,我收到你的回覆了,那條消息你可以刪除了,然後服務器又回覆發佈者我做完了,最後發佈者斷開連接。

 

 

QOS 3 (mqtt 預留的信息類型待用。這裏就沒測試的必要了)

 

 

 

DUP flag(打開標誌)

保證消息可靠傳輸,默認爲0,只佔用一個字節,表示第一次發送。不能用於檢測消息重複發送等。只適用於客戶端或服務器端嘗試重發PUBLISH, PUBREL, SUBSCRIBE UNSUBSCRIBE消息,注意需要滿足以下條件:當QoS > 0 消息需要回復確認此時,在可變頭部需要包含消息ID。當值爲1時,表示當前消息先前已經被傳送過。

 

 

QoS(Quality of Service,服務質量)

使用兩個二進制表示PUBLISH類型消息:

QoS value

bit 2

bit 1

Description

0

0

0

至多一次

發完即丟棄

<=1

1

0

1

至少一次

需要確認回覆

>=1

2

1

0

只有一次

需要確認回覆

=1

3

1

1

待用,保留位置

 

 

 

 

 

 

RETAIN(保持)

僅針對PUBLISH消息。不同值,不同含義:

 

 

1:表示發送的消息需要一直持久保存(不受服務器重啓影響),不但要發送給當前的訂閱者,並且以後新來的訂閱了此Topic name的訂閱者會馬上得到推送。

 

 

 

 

 這裏我設置爲true 也就是1,測試的topictestRetain

 

 

 

這裏我先讓一個訂閱者jieshou訂閱一個testRetain,現在來測試下發布者發佈一條消息的結果。這裏發佈者已經發布了一條消息

 



 

 已經訂閱的訂閱者已經接受到了消息

現在再來啓動第二個訂閱者訂閱者叫jieshou2

 

 



 

新來的訂閱者也接受到了該信息。備註:新來乍到的訂閱者,只會取出最新的一個RETAIN flag = 1的消息推送。

 

 

 

0:僅僅爲當前訂閱者推送此消息。

 

假如服務器收到一個空消息體(zero-length payload)RETAIN = 1、已存在Topic namePUBLISH消息,服務器可以刪除掉對應的已被持久化的PUBLISH消息。

 



 

發送者發送一條消息給訂閱方。



 

開啓第二個新訂閱者



 

新的訂閱者沒有接收到消息

 

 

 

Remaining Length(剩餘長度)

在當前消息中剩餘的byte(字節)數,包含可變頭部和負荷(稱之爲內容/body,更爲合適)。單個字節最大值:0111111116進制:0x7F10進製爲127。單個字節爲什麼不能是111111110xFF)呢?因爲MQTT協議規定,第八位(最高位)若爲1,則表示還有後續字節存在。同時MQTT協議最多允許4個字節表示剩餘長度。那麼最大長度爲:0xFF,0xFF,0xFF,0x7F,二進制表示爲:11111111,11111111,11111111,01111111,十進制:268435455 byte=261120KB=256MB=0.25GB 四個字節之間值的範圍:

 

Digits

From

To

1

0 (0x00)

127 (0x7F)

2

128 (0x80, 0x01)

16 383 (0xFF, 0x7F)

3

16 384 (0x80, 0x80, 0x01)

2 097 151 (0xFF, 0xFF, 0x7F)

4

2 097 152 (0x80, 0x80, 0x80, 0x01)

268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

 

固定頭部僅定義了消息類型和一些標誌位,一些消息的元數據,需要放入可變頭部中。可變頭部內容字節長度 + Playload/負荷字節長度 = 剩餘長度,這個是需要牢記的。可變頭部,包含了協議名稱,版本號,連接標誌,用戶授權,心跳時間等內容。

消息體主要是爲配合固定/可變頭部命令(比如CONNECT可變頭部User name標記若爲1則需要在消息體中附加用戶名稱字符串)而存在。

CONNECT/SUBSCRIBE/SUBACK/PUBLISH等消息有消息體。PUBLISH的消息體以二進制形式對待。

我這裏使用的是paho mqtt框架所以消息體中二進制轉義等一系列功夫就不需要關心太多,只需要記住mqtt協議消息體最大容量和消息的表現形式就可以了。具體轉義實現可以參考:http://www.blogjava.net/yongboy/archive/2014/02/07/409587.html

 

 

 

 

當我強制關閉客戶端程序的時候



 
也就是mqtt協議特點  Last Will Testament 特性通知有關各方客戶端異常中斷的機制。  ·

 

其他問題參考文獻:http://www.blogjava.net/yongboy/archive/2014/02/07/409587.html

 

http://blog.csdn.net/u013944791/article/details/44218471

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章