當(dāng)前位置:首頁(yè) > IT技術(shù) > 其他 > 正文

MQTT 入門(2)--MQTT 發(fā)布訂閱詳解
2022-05-29 22:25:22

本文主要介紹 MQTT 協(xié)議中發(fā)布訂閱的詳細(xì)過(guò)程。

1、Connect(連接)

MQTT 協(xié)議基于 TCP/IP 協(xié)議,MQTT Broker 和 Client 都有需要有 TCP/IP 地址。Client 連接?MQTT Broker 時(shí)有如下相關(guān)配置項(xiàng):

Client ID

服務(wù)端使用 ClientId 識(shí)別客戶端。連接服務(wù)端的每個(gè)客戶端都有唯一的 ClientId 。客戶端和服務(wù)端都必須使用 ClientId 識(shí)別兩者之間的?MQTT 會(huì)話相關(guān)的狀態(tài)。

ClientId 必須存在,但是服務(wù)端可以允許客戶端提供一個(gè)零字節(jié)的 ClientId,如果這樣做了,服務(wù)端必須將這看作特殊情況并分配唯一的 ClientId 給那個(gè)客戶端。然后正常處理這個(gè) CONNECT 報(bào)文。

Username/Password

MQTT 可以通過(guò)發(fā)送用戶名和密碼來(lái)進(jìn)行相關(guān)的認(rèn)證和授權(quán),但是,如果此信息未加密,則用戶名和密碼是以明文的方式發(fā)送的。

Keep Alive

保持連接(Keep Alive)是一個(gè)以秒為單位的時(shí)間間隔,它是指在客戶端傳輸完成一個(gè)控制報(bào)文的時(shí)刻到發(fā)送下一個(gè)報(bào)文的時(shí)刻,兩者之間允許空閑的最大時(shí)間間隔??蛻舳素?fù)責(zé)保證控制報(bào)文發(fā)送的時(shí)間間隔不超過(guò)保持連接的值。如果沒(méi)有任何其它的控制報(bào)文可以發(fā)送,客戶端必須發(fā)送一個(gè) PINGREQ 報(bào)文。

如果 Keep Alive 的值非零,并且服務(wù)端在一點(diǎn)五倍的 Keep Alive 時(shí)間內(nèi)沒(méi)有收到客戶端的控制報(bào)文,它必須斷開(kāi)客戶端的網(wǎng)絡(luò)連接,認(rèn)為網(wǎng)絡(luò)連接已斷開(kāi)。

Clean Session

客戶端和服務(wù)端可以保存會(huì)話狀態(tài),以支持跨網(wǎng)絡(luò)連接的可靠消息傳輸,這個(gè)標(biāo)志告訴服務(wù)器這次連接是不是一個(gè)全新的連接。

客戶端的會(huì)話狀態(tài)包括:

  • 已經(jīng)發(fā)送給服務(wù)端,但是還沒(méi)有完成確認(rèn)的 QoS 1 和 QoS 2 級(jí)別的消息
  • 已從服務(wù)端接收,但是還沒(méi)有完成確認(rèn)的 QoS 2 級(jí)別的消息。

服務(wù)端的會(huì)話狀態(tài)包括:

  • 會(huì)話是否存在,即使會(huì)話狀態(tài)的其它部分都是空。
  • 客戶端的訂閱信息。
  • 已經(jīng)發(fā)送給客戶端,但是還沒(méi)有完成確認(rèn)的 QoS 1 和 QoS 2 級(jí)別的消息。
  • 即將傳輸給客戶端的 QoS 1和 QoS 2 級(jí)別的消息。
  • 已從客戶端接收,但是還沒(méi)有完成確認(rèn)的 QoS 2 級(jí)別的消息。
  • 可選,準(zhǔn)備發(fā)送給客戶端的 QoS 0 級(jí)別的消息。

如果 CleanSession 標(biāo)志被設(shè)置為 1,客戶端和服務(wù)端必須丟棄之前的任何會(huì)話并開(kāi)始一個(gè)新的會(huì)話。會(huì)話僅持續(xù)和網(wǎng)絡(luò)連接同樣長(zhǎng)的時(shí)間。

如果 CleanSession 標(biāo)志被設(shè)置為 0,服務(wù)端必須基于當(dāng)前會(huì)話(使用 ClientId 識(shí)別)的狀態(tài)恢復(fù)與客戶端的通信。如果沒(méi)有與這個(gè)客戶端標(biāo)識(shí)符關(guān)聯(lián)的會(huì)話,服務(wù)端必須創(chuàng)建一個(gè)新的會(huì)話。當(dāng)連接斷開(kāi)后,客戶端和服務(wù)端必須保存會(huì)話信息。

2、Connack(確認(rèn)連接請(qǐng)求)

客戶端發(fā)送 Connect 報(bào)文請(qǐng)求對(duì)服務(wù)器的連接,服務(wù)器必須發(fā)送 Connack 報(bào)文作為對(duì) 來(lái)自客戶端的 Connect 報(bào)文的回應(yīng)。如果客戶端在合理的時(shí)間內(nèi)沒(méi)有收到服務(wù)端的CONNACK報(bào)文,客戶端應(yīng)該關(guān)閉網(wǎng)絡(luò)連接。合理的時(shí)間取決于應(yīng)用的類型和通信基礎(chǔ)設(shè)施。

Connack 報(bào)文包含 Session Present 和 Connect Return code 兩個(gè)重要的標(biāo)志。

Session Present

Session Present 標(biāo)志表示當(dāng)前會(huì)話是否是一個(gè)新的會(huì)話,如果服務(wù)端收到 CleanSession 標(biāo)志為1的連接,Connack報(bào)文中的 SessionPresent 標(biāo)志為 0 。如果服務(wù)端收到一個(gè) CleanSession 為0的連接,SessionPresent 標(biāo)志的值取決于服務(wù)端是否已經(jīng)保存了 ClientId 對(duì)應(yīng)客戶端的會(huì)話狀態(tài)。如果服務(wù)端已經(jīng)保存了會(huì)話狀態(tài),Connack 報(bào)文中的 SessionPresent 標(biāo)志為 1,如果服務(wù)端沒(méi)有已保存的會(huì)話狀態(tài),Connack 報(bào)文中的 SessionPresent 標(biāo)志為 0.

Connect Return code

Connect Return code 表示服務(wù)器對(duì)此次 Connect 的回應(yīng),0 表示連接已被服務(wù)器接受。如果服務(wù)端收到一個(gè)合法的 CONNECT 報(bào)文,但出于某些原因無(wú)法處理它,服務(wù)端應(yīng)該嘗試發(fā)送一個(gè)包含非零返回碼(表格中的某一個(gè))的 CONNACK 報(bào)文。如果服務(wù)端發(fā)送了一個(gè)包含非零返回碼的CONNACK 報(bào)文,那么它必須關(guān)閉網(wǎng)絡(luò)連接。

返回碼響應(yīng)描述
0 0x00連接已接受 連接已被服務(wù)端接受
1 0x01連接已拒絕,不支持的協(xié)議版本 服務(wù)端不支持客戶端請(qǐng)求的MQTT協(xié)議級(jí)別
2 0x02連接已拒絕,不合格的客戶端標(biāo)識(shí)符 客戶端標(biāo)識(shí)符是正確的UTF-8編碼,但服務(wù)端不允許使用
3 0x03連接已拒絕,服務(wù)端不可用 網(wǎng)絡(luò)連接已建立,但MQTT服務(wù)不可用
4 0x04連接已拒絕,無(wú)效的用戶名或密碼 用戶名或密碼的數(shù)據(jù)格式無(wú)效
5 0x05連接已拒絕,未授權(quán) 客戶端未被授權(quán)連接到此服務(wù)器
6-255 ? 保留

如果認(rèn)為上表中的所有連接返回碼都不太合適,那么服務(wù)端必須關(guān)閉網(wǎng)絡(luò)連接,不需要發(fā)送CONNACK 報(bào)文。

3、Subscribe(訂閱主題)

客戶端向服務(wù)端發(fā)送 Subscribe 報(bào)文用于創(chuàng)建一個(gè)或多個(gè)訂閱。每個(gè)訂閱注冊(cè)客戶端關(guān)心的一個(gè)或多個(gè)主題。為了將應(yīng)用消息轉(zhuǎn)發(fā)給與那些訂閱匹配的主題,服務(wù)端發(fā)送 Publish 報(bào)文給客戶端。Subscribe 報(bào)文為每個(gè)訂閱指定了最大的 QoS 等級(jí),服務(wù)端根據(jù)這個(gè)發(fā)送應(yīng)用消息給客戶端。

Subscribe 報(bào)文的有效載荷必須包含至少一對(duì)主題過(guò)濾器 和 QoS 等級(jí)字段組合。沒(méi)有有效載荷的 Subscribe 報(bào)文是違反協(xié)議的。

4、Suback(訂閱確認(rèn))

服務(wù)端發(fā)送 Suback 報(bào)文給客戶端,用于確認(rèn)它已收到并且正在處理 Subscribe 報(bào)文。

Suback 報(bào)文包含一個(gè)原因碼列表,用于指定授予的最大QoS等級(jí)或 Subscribe 報(bào)文所請(qǐng)求的每個(gè)訂閱發(fā)生的錯(cuò)誤,每個(gè)原因碼對(duì)應(yīng) Subscribe 報(bào)文中的一個(gè)主題過(guò)濾器。Suback 報(bào)文中的原因碼順序必須與 Subscribe 報(bào)文中的主題過(guò)濾器順序相匹配。

允許的返回碼值:

  • 0x00 - 最大QoS 0
  • 0x01 - 成功 – 最大QoS 1
  • 0x02 - 成功 – 最大 QoS 2
  • 0x80 - Failure 失敗

5、Publish(發(fā)布消息)

Publish 報(bào)文是指從客戶端向服務(wù)端或者服務(wù)端向客戶端傳輸一個(gè)應(yīng)用消息,服務(wù)器收到 Publish 報(bào)文后根據(jù)主題過(guò)濾器將消息轉(zhuǎn)發(fā)給其他客戶端。

發(fā)布消息時(shí)有如下配置項(xiàng):

Topic

主題名(Topic Name)用于識(shí)別消息應(yīng)該被發(fā)布到哪一個(gè)會(huì)話,服務(wù)端發(fā)送給訂閱客戶端的 Publish 報(bào)文的主題名必須匹配該訂閱的主題過(guò)濾器。

QoS

QoS 表示應(yīng)用消息分發(fā)的服務(wù)質(zhì)量等級(jí)保證

QoS值Bit 2Bit 1描述
0 0 0 最多分發(fā)一次
1 0 1 至少分發(fā)一次
2 1 0 只分發(fā)一次
- 1 1 保留位

Publish 報(bào)文不能將 QoS 所有的位設(shè)置為 1。如果服務(wù)端或客戶端收到 QoS 所有位都為 1 的 Publish 報(bào)文,它必須關(guān)閉網(wǎng)絡(luò)連接。

Retain

如果客戶端發(fā)給服務(wù)端的 Publish 報(bào)文的保留(RETAIN)標(biāo)志被設(shè)置為 1,服務(wù)端必須存儲(chǔ)這個(gè)應(yīng)用消息和它的服務(wù)質(zhì)量等級(jí)(QoS),以便它可以被分發(fā)給未來(lái)的主題名匹配的訂閱者 。一個(gè)新的訂閱建立時(shí),對(duì)每個(gè)匹配的主題名,如果存在最近保留的消息,它必須被發(fā)送給這個(gè)訂閱者。如果服務(wù)端收到一條保留(RETAIN)標(biāo)志為1的Q消息,它必須丟棄之前為那個(gè)主題保留的任何消息,并將這個(gè)新的消息當(dāng)作那個(gè)主題的新保留消息。

保留標(biāo)志為 1 且有效載荷為零字節(jié)的 Publish 報(bào)文會(huì)被服務(wù)端當(dāng)作正常消息處理,它會(huì)被發(fā)送給訂閱主題匹配的客戶端。此外,同一個(gè)主題下任何現(xiàn)存的保留消息必須被移除,因此這個(gè)主題之后的任何訂閱者都不會(huì)收到保留消息。

服務(wù)端發(fā)送 Publish 報(bào)文給客戶端時(shí),如果消息是作為客戶端一個(gè)新訂閱的結(jié)果發(fā)送,它必須將報(bào)文的保留標(biāo)志設(shè)為 1。當(dāng)一個(gè) Publish 報(bào)文發(fā)送給客戶端是因?yàn)槠ヅ湟粋€(gè)已建立的訂閱時(shí),服務(wù)端必須將保留標(biāo)志設(shè)為 0,不管它收到的這個(gè)消息中保留標(biāo)志的值是多少。

如果客戶端發(fā)給服務(wù)端的 Publish 報(bào)文的保留標(biāo)志位 0,服務(wù)端不能存儲(chǔ)這個(gè)消息也不能移除或替換任何現(xiàn)存的保留消息。

Payload

有效載荷包含將被發(fā)布的應(yīng)用消息。數(shù)據(jù)的內(nèi)容和格式是應(yīng)用特定的,可以發(fā)送圖像,任何編碼的文本,加密的數(shù)據(jù)以及幾乎所有二進(jìn)制數(shù)據(jù)。

?

?

參考:https://www.emqx.com/zh/blog/how-to-use-mqtt-packet-to-implement-publishing-and-subscribing-functions

本文摘自 :https://www.cnblogs.com/

開(kāi)通會(huì)員,享受整站包年服務(wù)立即開(kāi)通 >