MQTT 5.0 報文解析 04:PINGREQ 與 PINGRESP

歡迎閱讀 MQTT 5.0 報文系列 的第四篇文章。在上一篇中,我們已經介紹了 MQTT 5.0 中的 SUBSCRIBE 報文和 UNSUBSCRIBE 報文。現在,我們將介紹用於維持連接的控制報文:PINGREQ 和 PINGRESP。

除了用於連接、發佈和訂閱的控制報文,MQTT 還有一類報文用於在客戶端和服務端之間模擬心跳,以達到保持連接的目的,它們分別是 PINGREQ 報文和 PINGRESP 報文,我們通常也會稱它們爲心跳報文。

客戶端定期向服務端發送 PINGREQ 報文,服務端可以由此得知連接良好且客戶端仍然活躍。每收到一個 PINGREQ 報文,服務端就會回覆一個 PINGRESP 報文,因此客戶端也可以由此得知連接良好且服務端仍然活躍。

報文示例

我們使用 MQTTX CLI公共 MQTT 服務器 發起一個客戶端連接,不發佈消息也不訂閱主題,但我們仍然可以在 Wireshark 中看到客戶端和服務端之間總是週期性地出現 MQTT 報文的往返,這些報文就是 PINGREQ 和 PINGRESP 報文。

以下命令將創建一個 Keep Alive 爲 5 秒的客戶端連接,這可以讓我們儘快看到客戶端發送 PINGREQ 報文:

mqttx conn --hostname broker.emqx.io --mqtt-version 5 --keepalive 5

我們會發現 PINGREQ 和 PINGRESP 報文總是隻有 2 個字節的大小,並且它們的內容似乎也永遠不會發生變化:

# PINGREQ
c0 00
# PINGRESP
d0 00

這是因爲這兩個報文有着非常簡單的報文結構。

PINGREQ & PINGRESP 報文結構

PINGREQ 和 PINGRESP 報文的區別僅僅是固定報頭中報文類型的不同,12(0xC)表示這是一個 PINGREQ 報文,13(0xD)則表示這是一個 PINGRESP 報文。

因爲 PINGREQ 和 PINGRESP 報文均不包含可變報頭有效載荷,所以它們的固定報頭中剩餘長度字段的值永遠都是 0。

PING 報文.png

這種報文結構讓 PINGREQ 和 PINGRESP 報文的大小降到了最低,所以發送它們並不會佔用太多的帶寬。

總結

PINGREQ 和 PINGRESP 是 MQTT 中最簡單的報文類型,它們的內容固定不變。我們唯一可以改變的,就是通過連接時的 Keep Alive 選項,影響客戶端發送 PINGREQ 報文的頻率。

如果服務端沒有在 1.5 倍 Keep Alive 時間內收到客戶端發送的任何控制報文,就會認爲客戶端處於非活躍狀態或網絡異常而斷開連接。在本文的報文示例中,我們在連接時 Keep Alive 設置爲 5 秒,那麼對服務端來說超時時間就是 7.5 秒。

對於客戶端來說,如果在發送 PINGREQ 報文之後的一段時間內,沒有收到服務端返回的 PINRESP 報文,那麼它應該斷開連接。這個時間的長短,主要取決於客戶端對網絡延遲的預期以及各個客戶端 SDK 的具體實現。

現在,我們對 MQTT 報文的瞭解又更進了一步,在下一篇文章中我們將繼續介紹在斷開連接時使用的 DISCONNECT 報文。

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