亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

計算機網(wǎng)絡編程MQTT協(xié)議基礎原理詳解

 更新時間:2021年11月23日 15:06:07   作者:程序員cxuan  
這篇文章主要為大家介紹了計算機編程MQTT協(xié)議的基礎原理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪

之前有位讀者給我留言說想要了解一下什么是 MQTT 協(xié)議,順便還把我夸了一把,有點不好意思啦。

那么讀者的要求必須要滿足啊,所以現(xiàn)在 @一下這位小姐姐,來聽課啦!

什么是 MQTT 協(xié)議

MQTT 協(xié)議的全稱是 Message Queuing Telemetry Transport,翻譯為消息隊列傳輸探測,它是 ISO 標準下的一種基于發(fā)布 - 訂閱模式的消息協(xié)議,它是基于 TCP/IP 協(xié)議簇的,它是為了改善網(wǎng)絡設備硬件的性能和網(wǎng)絡的性能來設計的。MQTT 一般多用于 IoT 即物聯(lián)網(wǎng)上,廣泛應用于工業(yè)級別的應用場景,比如汽車、制造、石油、天然氣等。

img

在了解了 MQTT 的概念和應用場景后,我們下來就來走進 MQTT 的學習中了,先來看一下 MQTT 有哪些概念。

MQTT 基礎

上面我們解釋了 MQTT 協(xié)議的基本概念,MQTT 協(xié)議總結(jié)一點就是一種輕量級的二進制協(xié)議,MQTT 協(xié)議與 HTTP 相比具有一個明顯的優(yōu)勢:數(shù)據(jù)包開銷較小,數(shù)據(jù)包開銷小就意味著更容易進行網(wǎng)絡傳輸。還有一個優(yōu)勢就是 MQTT 在客戶端容易實現(xiàn),而且具有易用性,非常適合當今資源有限的設備。

你可能對這些概念有些諱莫如深,為什么具有 xxx 這種特性呢?這就需要從 MQTT 的設計說起了。

MQTT 協(xié)議由 Andy Stanford-Clark (IBM) 和 Arlen Nipper(Arcom,現(xiàn)為 Cirrus Link)于 1999 年發(fā)明。 他們需要一種通過衛(wèi)星連接石油管道的協(xié)議,以最大限度地減少電池損耗和帶寬。所以他們?yōu)檫@個協(xié)議規(guī)定了幾種要求:

  • 這個協(xié)議必須易于實現(xiàn);
  • 這個協(xié)議中的數(shù)據(jù)必須易于傳輸,消耗成本?。?/li>
  • 這個協(xié)議必須提供服務質(zhì)量管理;
  • 這個協(xié)議必須支持連續(xù)的會話控制
  • 假設數(shù)據(jù)不可知,不強求傳輸數(shù)據(jù)的類型與格式,保持靈活性。

這些設計也是 MQTT 的精髓所在,MQTT 經(jīng)過不斷的發(fā)展,已經(jīng)成為了物聯(lián)網(wǎng) IoT 所必備的一種消息探測協(xié)議,官方強烈推薦使用的版本是 MQTT 5。

發(fā)布 - 訂閱模式

發(fā)布 - 訂閱模式我相信接觸消息中間件架構的同學都聽過,這是一種傳統(tǒng)的客戶端 - 服務器架構的替代方案,因為一般傳統(tǒng)的客戶端-服務器是客戶端能夠直接和服務器進行通信。

但是發(fā)布 - 訂閱模式 pub/sub就不一樣了,發(fā)布訂閱模式會將發(fā)送消息的發(fā)布者 publisher與接收消息的訂閱者 subscribers進行分離,publisher 與 subscribers 并不會直接通信,他們甚至都不清楚對方是否存在,他們之間的交流由第三方組件 broker 代理。

pub/sub 最重要的方面是 publisher 與 subscriber 的解藕,這種耦合度有下面三個維度:

  • 空間解耦:publisher 與 subscriber 并不知道對方的存在,例如不會有 IP 地址和端口的交互,也更不會有消息的交互。
  • 時間解藕:publisher 與 subscriber 并不一定需要同時運行。
  • 同步 Synchronization 解藕:兩個組件的操作比如 publish 和 subscribe 都不會在發(fā)布或者接收過程中產(chǎn)生中斷。

總之,發(fā)布/訂閱模式消除了傳統(tǒng)客戶-服務器之間的直接通信,把通信這個操作交給了 broker 進行代理,并在空間、時間、同步三個維度上進行了解藕。

可拓展性

pub/sub 比傳統(tǒng)的客戶端-服務器模式有了更好的拓展,這是由于 broker 的高度并行化,并且是基于事件驅(qū)動的模式??赏卣剐赃€體現(xiàn)在消息的緩存和消息的智能路由,還可以通過集群代理來實現(xiàn)數(shù)百萬的連接,使用負載均衡器將負載分配到更多的單個服務器上,這就是 MQTT 的深度應用了。

你可能不明白什么是事件驅(qū)動,我在這里解釋下事件驅(qū)動的概念。

事件驅(qū)動是一種編程范式,編程范式是軟件工程中的概念,它指的是一種編程方法或者說程序設計方式,比如說面向?qū)ο缶幊毯兔嫦蜻^程編程就是一種編程范式,事件驅(qū)動中的程序流程會由諸如用戶操作(點擊鼠標、鍵盤)、傳感器輸出或者從其他程序或傳遞的消息事件決定。事件驅(qū)動編程是圖形用戶界面和其他應用程序比如 Web 中使用的主要范式,這些應用程序能夠響應用戶輸入執(zhí)行某些操作為中心,這同時也適用于驅(qū)動程序的編程。

消息過濾

在 pub/sub 的架構模式中,broker 扮演著至關重要的作用,其中非常重要的一點就是 broker 能夠?qū)ο⑦M行過濾,使每個訂閱者只接收自己感興趣的消息。

broker 有幾個可以過濾的選項

基于主題的過濾

MQTT 是基于 subject 的消息過濾的,每條消息都會有一個 topic ,接收客戶端會向 borker 訂閱感興趣的 topic,訂閱后,broker 就會確保客戶端收到發(fā)布到 topic 中的消息。

基于內(nèi)容的過濾

在基于內(nèi)容的過濾中,broker 會根據(jù)特定的內(nèi)容過濾消息,接受客戶端會經(jīng)過過濾他們感興趣的內(nèi)容。這種方法的一個顯著的缺點就是必須事先知道消息的內(nèi)容,不能加密或者輕易修改。

基于類型的過濾

在使用面向?qū)ο蟮恼Z言時,基于消息(事件)的類型過濾是一種比較常見的過濾方式。

為了發(fā)布/訂閱系統(tǒng)的挑戰(zhàn),MQTT 具有三個服務質(zhì)量級別,你可以指定消息從客戶端傳到 broker 或者從 broker 傳到客戶端,在 topic 的訂閱中,會存在 topic 沒有 subscriber 訂閱的情況,作為 broker 必須知道如何處理這種情況。

MQTT 與消息隊列的區(qū)別

我們現(xiàn)在知道,MQTT 是一種消息隊列傳輸探測協(xié)議,這種協(xié)議是看似是以消息隊列為基礎,但卻與消息隊列有所差別。

在傳統(tǒng)的消息隊列模式中,一條消息會存儲在消息隊列中等待被消費,每個傳入的消息都存儲在消息隊列中,直到它被客戶端(通常稱之為消費者)所接收,如果沒有客戶端消費消息的話,這條消息就會存在消息隊列中等待被消費。但是在消息隊列中,不會存在消息沒有客戶端消費的情況,但是在 MQTT 中,確存在 topic 無 subscriber 訂閱的情況。

在傳統(tǒng)的消息隊列模式中,一條消息只能被一個客戶端所消費,負載會分布在隊列的每個消費者之間;而在 MQTT 中,每個訂閱者都會受到消息,每個訂閱者有相同的負載。

在傳統(tǒng)的消息隊列模式中,必須使用單獨的命令來顯式創(chuàng)建隊列,只有隊列創(chuàng)建后,才可以生產(chǎn)或者消費消息;而在 MQTT 中,topic 比較靈活,可以即時創(chuàng)建。

HiveMQ 現(xiàn)在是開源的,HiveMQ 社區(qū)版實現(xiàn)了 MQTT broker 規(guī)范,并兼容了 MQTT 3.1、3.1.1 和 MQTT 5。HiveMQ MQTT Client 是一個基于 Java 的 MQTT 客戶端實現(xiàn),兼容 MQTT 3.1.1 和 MQTT 5。這兩個項目都可以在 HiveMQ 的 github https://github.com/hivemq 上找到。

我們知道,broker 將 publisher 和 subscriber 進行分離,因此客戶端的連接由 broker 代理,所以在我們深入理解 MQTT 之前,我們需要先知道客戶端和代理的含義。

MQTT 重要概念

MQTT client

當我們討論關于客戶端的概念時,一般指的就是 MQTT Client,publisher 和 subscriber 都屬于 MQTT Client。之所以有發(fā)布者和訂閱者這個概念,其實是一種相對的概念,就是指當前客戶端是在發(fā)布消息還是在接收消息,發(fā)布和訂閱的功能也可以由同一個 MQTT Client 實現(xiàn)。

MQTT 客戶端是指運行 MQTT 庫并通過網(wǎng)絡連接到 MQTT broker 的任何設備,這些設備可以從微控制器到成熟的服務器?;旧希魏问褂?TCP/IP 協(xié)議使用 MQTT 設備的都可以稱之為 MQTT Client。MQTT 協(xié)議的客戶端實現(xiàn)非常簡單直接。易于實施是 MQTT 非常適合小型設備的原因之一。 MQTT 客戶端庫可用于多種編程語言。 例如,Android、Arduino、C、C++、C#、Go、iOS、Java、JavaScript 和 .NET。

MQTT broker

與 MQTT client 對應的就是 MQTT broker,broker 是任何發(fā)布/訂閱機構的核心,根據(jù)實現(xiàn)的不同,代理可以處理多達數(shù)百萬連接的 MQTT client。

broker 負責接收所有消息,過濾消息,確定是哪個 client 訂閱了每條消息,并將消息發(fā)送給對應的 client,broker 還負責保存會話數(shù)據(jù),這些數(shù)據(jù)包括訂閱的和錯過的消息。broker 還負責客戶端的身份驗證和授權。

MQTT Connection

MQTT 是基于 TCP/IP 協(xié)議基礎之上的,所以 MQTT 的 client 和 broker 都需要 TCP/IP 協(xié)議的支持。

MQTT 的連接總是在 client 和 broker 之間進行,client 和 client 之間并不會相互連接。如果要發(fā)起連接的話,那么 client 就會向 broker 發(fā)起 CONNECT 消息,代理會使用 CONNACK 消息和狀態(tài)碼進行響應。一旦 client 和 broker 的連接建立后,broker 就會使客戶端的連接一直處于打開狀態(tài),直到 client 發(fā)出斷開命令或者連接中斷。

消息報文

MQTT 的消息報文主要分為 CONNECT 和 CONNACK 消息。

CONNECT

我們上面提到了為了初始化連接,需要 client 向 broker 發(fā)送 CONNECT 消息,如果這個 CONNECT 消息格式錯誤或者打開套接字(因為基于 TCP/IP 協(xié)議棧需要初始化 Socket 連接)時間過長,亦或是發(fā)送連接消息時間過長的話,broker 就會關閉這條連接。

一個 MQTT 客戶端發(fā)送一條 CONNECT 連接,這條 CONNECT 連接可能會包含下面這些信息:

我這里解釋一下這些信息都是什么概念

ClientId:顯而易見,這個就是每個客戶端的 ID 標識,也就是連接到 MQTT broker 的每個 client。這個 ID 應該是每個 client 和 broker 唯一的,如果你不需要 broker 持有狀態(tài)的話,你可以發(fā)送一個空的 ClientId,空的 ClientId 會沒有任何狀態(tài)。在這種情況下,ClientSession 需要設置為 true,否則將會拒絕連接。

clientSession 是什么我們下面會說。

CleanSession:CleanSession 會話標志會告訴 broker client 是否需要建立持久會話。在持久會話 (CleanSession = false)中,broker 存儲 client 的所有訂閱以及服務質(zhì)量(Qos) 是 1 或 2 訂閱的 client 的所有丟失的消息。如果會話不是持久的(CleanSession = true),那么 broker 則不會為 client 存儲任何內(nèi)容并且會清除先前持久會話中的所有信息。

Username/Password :MQTT 會發(fā)送 username 和 password 進行 client 認證和授權。如果此信息沒有經(jīng)過加密或者 hash ,那么密碼將會以純文本的形式發(fā)送。所以,一般強烈建議 username 和 password 要經(jīng)過加密安全傳輸。像 HiveMQ 這樣的 broker 可以與 SSL 證書進行身份驗證,因此不需要用戶名和密碼。LastWillxxx :LastWillxxx 表示的是遺愿,client 在連接 broker 的時候?qū)O立一個遺愿,這個遺愿會保存在 broker 中,當 client 因為非正常原因斷開與 broker 的連接時,broker 會將遺愿發(fā)送給訂閱了這個 topic(訂閱遺愿的 topic)的 client。

keepAlive:keepAlive 是 client 在連接建立時與 broker 通信的時間間隔,通常以秒為單位。這個時間指的是 client 與 broker 在不發(fā)送消息下所能承受的最大時長。

在聊完 client 與 broker 之間發(fā)送建立連接的 CONNECT 消息后,我們再來聊一下 broker 需要對 CONNECT 進行確認的 CONNACK 消息。

CONNACK

當 broker 收到 CONNECT 消息時,它有義務回復 CONNACK 消息進行響應。CONNACK 消息包括兩部分內(nèi)容

SessionPresent:會話當前標識,這個標志會告訴 client 當前 broker 是否有一個持久性會話與 client 進行交互。SessionPresent 標志和 CleanSession 標志有關,當 client 在 CleanSession 設置為 true 的情況下連接時,SessionPresent 始終為 false,因為沒有持久性會話可以使用。如果 CleanSession 設置為 false,則有兩種可能性,如果 ClientId 的會話信息可用,并且 broker 已經(jīng)存儲了會話信息,那么 SessionPresent 為 true,否則如果沒有 ClientId 的任何會話信息,那么 SessionPresent 為 false。

ReturnCode:CONNACK 消息中的第二個標志是連接確認標志。這個標志包含一個返回碼,告訴客戶端連接嘗試是否成功。連接確認標志有下面這些選項。

關于每個連接的詳細說明,可以參考

https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718035

消息類型

發(fā)布

當 MQTT client 在連接到 broker 之后就可以發(fā)送消息了,MQTT 使用的是基于 topic 主題的過濾。每條消息都應該包含一個 topic ,broker 可以使用 topic 將消息發(fā)送給感興趣的 client。除此之外,每條消息還會包含一個負載(Payload),Payload 中包含要以字節(jié)形式發(fā)送的數(shù)據(jù)。

MQTT 是數(shù)據(jù)無關性的,也就是說數(shù)據(jù)是由發(fā)布者 - publisher 決定要發(fā)送的是 XML 、JSON 還是二進制數(shù)據(jù)、文本數(shù)據(jù)。

MQTT 中的 PUBLISH 消息結(jié)構如下。

Packet Identifier:這個 PacketId 標識在 client 和 broker 之間唯一的消息標識。packetId 僅與大于零的 Qos 級別相關。

TopicName:主題名稱是一個簡單的字符串,/ 代表著分層結(jié)構。

Qos:這個數(shù)字表示的是服務質(zhì)量水平,服務質(zhì)量水平有三個等級:0、1 和 2,服務級別決定了消息到達 client 或者 broker 的保證類型,來決定消息是否丟失。

RetainFlag:這個標志表示 broker 將最近收到的一條 RETAIN 標志位為true的消息保存在服務器端(內(nèi)存或者文件)。

MQTT 服務器只會為每一個 Topic 保存最近收到的一條 RETAIN 標志位為true的消息。也就是說,如果MQTT 服務器上已經(jīng)為某個 Topic 保存了一條 Retained 消息,當客戶端再次發(fā)布一條新的 Retained 消息時,那么服務器上原來的那條消息會被覆蓋。

Payload:這個是每條消息的實際內(nèi)容。MQTT 是數(shù)據(jù)無關性的??梢园l(fā)送任何文本、圖像、加密數(shù)據(jù)以及二進制數(shù)據(jù)。

Dupflag:這個標志表示該消息是重復的并且由于預期的 client 或者 broker 沒有確認所以重新發(fā)送了一次。這個標志僅僅與 Qos 大于 0 相關。

當 client 向 broker 發(fā)送消息時,broker 會讀取消息,根據(jù) Qos 的級別進行消息確認,然后處理消息。處理消息其實就是確定哪些 subscriber 訂閱了 topic 并將消息發(fā)送給他們。

最初發(fā)布消息的 client 只關心將 PUBLISH 消息發(fā)送給 broker,一旦 broker 收到 PUBLISH 消息,broker 就有責任將其傳遞給所有 subscriber。發(fā)布消息的 client 不會知道是否有人對發(fā)布的消息感興趣,同時也不知道多少 client 從 broker 收到了消息。

訂閱

client 會向 broker 發(fā)送 SUBSCRIBE 消息來接收有關感興趣的 topic,這個 SUBSCRIBE 消息非常簡單,它包含了一個唯一的數(shù)據(jù)包標識和一個訂閱列表。

Packet Identifier:這個 PacketId 和上面的 PacketId 一樣,都表示消息的唯一標識符。

ListOfSubscriptions:SUBSCRIBE 消息可以包含一個 client 的多個訂閱,每個訂閱都會由一個 topic 和一個 Qos 構成。訂閱消息中的 topic 可以包含通配符。

確認消息

client 在向 broker 發(fā)送 SUBSCRIBE 消息后,為了確認每個訂閱,broker 會向 client 發(fā)送 SUBACK 確認消息。這個 SUBACK 包含原始 SUBSCRIBE 消息的 packetId 和返回碼列表。

其中

Packet Identifier :這個數(shù)據(jù)包標識符和 SUBSCRIBE 中的相同。

ReturnCode:broker 為每個接收到的 SUBSCRIBE 消息的 topic/Qos 對發(fā)送一個返回碼。例如,如果 SUBSCRIBE 消息有五個訂閱消息,則 SUBACK 消息包含五個返回碼作為響應。

到現(xiàn)在我們已經(jīng)探討過了三種消息類型,發(fā)布 - 訂閱 - 確認消息,這三種消息的示意圖如下。

退訂

SUBSCRIBE 消息對應的是 UNSUBSCRIBE 消息,這條消息發(fā)送后,broker 會刪除關于 client 的訂閱。所以,UNSUBSCRIBE 消息與 SUBSCRIBE 消息類似,都具有 packetId 和 topic 列表。

確認退訂

取消訂閱也需要 broker 的確認,此時 broker 會向 client 發(fā)送一個 UNSUBACK 消息,這個 UNSUBACK 消息非常簡單,只有一個 packetId 數(shù)據(jù)標識符。

退訂和確認退訂的流程如下。

當 client 收到來自 broker 的 UNSUBACK 消息后,就可以認為 UNSUBSCRIBE 消息中的訂閱被刪除了。

聊聊 Topic

聊了這么多關于 MQTT 的內(nèi)容,但是我們還沒有好好聊過 Topic。在 MQTT 中,Topic 是指 broker 為每個連接的 client 過濾消息的 UTF-8 字符串。Topic 是一種分層的結(jié)構,可以由一個或者多個 Topic 組成。每個 Topic 由 / 進行分割。

與傳統(tǒng)的消息隊列相比,MQTT Topic 非常輕量級,client 在發(fā)布或訂閱之前不需要先創(chuàng)建所需要的 Topic,broker 在接收每個 Topic 前不用進行初始化操作。

通配符

當客戶端訂閱 Topic 時,它可以訂閱已發(fā)布消息的確切 Topic,也可以使用通配符來同時訂閱多個 Topic。通配符有兩種:單級和多級。

單級通配符

單級通配符可以替換 Topic 的一個級別,+ 號代表 Topic 中的單級通配符。

如果 Topic 包含任意字符串而不是通配符,則任何 Topic 都能夠和單級通配符匹配。例如

myhome/groundfloor/+/temperature 就有下面這幾種匹配方式。

多級通配符

多級通配符涵蓋多個 Topic,# 代表 Topic 中的多級通配符。為了讓 broker 能夠確定和哪些 Topic 匹配,多級通配符必須作為 Topic 中的最后一個字符放置,并以 / 開頭。

下面是 myhome/groundfloor/# 的幾個例子

當 client 訂閱帶有多級通配符的 Topic 時,不論 Topic 有多長多深,它都會收到通配符之前 Topic 的所有消息。如果你只將 Topic 定義為 # 的話,那么你將會收到所有的消息。

以上就是計算機編程MQTT協(xié)議基礎原理詳解的詳細內(nèi)容,更多關于計算機編程MQTT協(xié)議的資料請關注腳本之家其它相關文章!

相關文章

最新評論