日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

物联网 | 管中窥豹,一线工程师看MQTT

發布時間:2023/12/20 c/c++ 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 物联网 | 管中窥豹,一线工程师看MQTT 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

版權聲明:本文為CSDN博主「唐門教主」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/tangxiaoyin/article/details/76053348

MQTT是什么?

MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協議),是一種基于發布/訂閱(Publish/Subscribe)模式的輕量級通訊協議,該協議構建于TCP/IP協議上,由IBM在1999年發布。

MQTT最大的優點在于可以以極少的代碼和有限的帶寬,為遠程設備提供實時可靠的消息服務。做為一種低開銷、低帶寬占用的即時通訊協議,MQTT在物聯網、小型設備、移動應用等方面有廣泛的應用。

當然,在物聯網開發中,MQTT不是唯一的選擇,與MQTT互相競爭的協議有XMPP和CoAP協議等,文章末尾會有一個比較和說明。

MQTT是哪一層的協議?

眾所周知,TCP/IP參考模型可以分為四層:應用層、傳輸層、網絡層、鏈路層。TCP和UDP位于傳輸層,應用層常見的協議有HTTP、FTP、SSH等。MQTT協議運行于TCP之上,屬于應用層協議,因此只要是支持TCP/IP協議棧的地方,都可以使用MQTT。

MQTT消息格式

每條MQTT命令消息的消息頭都包含一個固定的報頭,有些消息會攜帶一個可變報文頭和一個負荷。消息格式如下:

固定報文頭 | 可變報文頭 | 負荷

固定報文頭(Fixed Header)

MQTT固定報文頭最少有兩個字節,第一字節包含消息類型(Message Type)和QoS級別等標志位。第二字節開始是剩余長度字段,該長度是后面的可變報文頭加消息負載的總長度,該字段最多允許四個字節。

剩余長度字段單個字節最大值為二進制0b0111 1111,16進制0x7F。也就是說,單個字節可以描述的最大長度是127字節。為什么不是256字節呢?因為MQTT協議規定,單個字節第八位(最高位)若為1,則表示后續還有字節存在,第八位起“延續位”的作用。

例如,數字64,編碼為一個字節,十進制表示為64,十六進制表示為0×40。數字321(65+2*128)編碼為兩個字節,重要性最低的放在前面,第一個字節為65+128=193(0xC1),第二個字節是2(0x02),表示2×128。

由于MQTT協議最多只允許使用四個字節表示剩余長度(如表1),并且最后一字節最大值只能是0x7F不能是0xFF,所以能發送的最大消息長度是256MB,而不是512MB。

可變報文頭(Variable Header)

可變報文頭主要包含協議名、協議版本、連接標志(Connect Flags)、心跳間隔時間(Keep Alive timer)、連接返回碼(Connect Return Code)、主題名(Topic Name)等,后面會針對主要部分進行講解。

有效負荷(Payload)

Payload直譯為負荷,可能讓人摸不著頭腦,實際上可以理解為消息主體(body)。

當MQTT發送的消息類型是CONNECT(連接)、PUBLISH(發布)、SUBSCRIBE(訂閱)、SUBACK(訂閱確認)、UNSUBSCRIBE(取消訂閱)時,則會帶有負荷。

MQTT的主要特性

MQTT的消息類型(Message Type)

固定報文頭中的第一個字節包含連接標志(Connect Flags),連接標志用來區分MQTT的消息類型。MQTT協議擁有14種不同的消息類型(如表2),可簡單分為連接及終止、發布和訂閱、QoS 2消息的機制以及各種確認ACK。至于每一個消息類型會攜帶什么內容,這里不多闡述。

消息質量(QoS)

MQTT消息質量有三個等級,QoS 0,QoS 1和 QoS 2。

  • QoS 0:最多分發一次。消息的傳遞完全依賴底層的TCP/IP網絡,協議里沒有定義應答和重試,消息要么只會到達服務端一次,要么根本沒有到達。
  • QoS 1:至少分發一次。服務器的消息接收由PUBACK消息進行確認,如果通信鏈路或發送設備異常,或者指定時間內沒有收到確認消息,發送端會重發這條在消息頭中設置了DUP位的消息。
  • QoS 2:只分發一次。這是最高級別的消息傳遞,消息丟失和重復都是不可接受的,使用這個服務質量等級會有額外的開銷。
    通過下面的例子可以更深刻的理解上面三個傳輸質量等級。

比如共享單車中,智能鎖可以定時使用QoS level 0質量消息請求服務器,發送單車的當前位置,如果服務器沒收到也沒關系,反正過一段時間又會再發送一次。

之后用戶可以通過App查詢周圍單車位置,找到單車后需要進行解鎖,這時候可以使用QoS level 1質量消息,手機App不斷的發送解鎖消息給單車鎖,確保有一次消息能達到以解鎖單車。

最后用戶用完單車后,需要提交付款表單,可以使用QoS level 2質量消息,這樣確保只傳遞一次數據,否則用戶就會多付錢了。

遺愿標志(Will Flag)

在可變報文頭的連接標志位字段(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字段可以應用于設備掉線后需要通知用戶的場景。

連接保活心跳機制(Keep Alive Timer)

MQTT客戶端可以設置一個心跳間隔時間(Keep Alive Timer),表示在每個心跳間隔時間內發送一條消息。如果在這個時間周期內,沒有業務數據相關的消息,客戶端會發一個PINGREQ消息,相應的,服務器會返回一個PINGRESP消息進行確認。

如果服務器在一個半(1.5)心跳間隔時間周期內沒有收到來自客戶端的消息,就會斷開與客戶端的連接。心跳間隔時間最大值大約可以設置為18個小時,0值意味著客戶端不斷開。

MQTT其他特點

異步發布/訂閱實現

發布/訂閱模式解耦了發布消息的客戶(發布者)與訂閱消息的客戶(訂閱者)之間的關系,這意味著發布者和訂閱者之間并不需要直接建立聯系。
這個模式有以下好處:

  • 發布者與訂閱者只需要知道同一個消息代理即可;
  • 發布者和訂閱者不需要直接交互;
  • 發布者和訂閱者不需要同時在線。

由于采用了發布/訂閱實現,MQTT可以雙向通信。也就是說MQTT支持服務端反向控制設備,設備可以訂閱某個主題,然后發布者對該主題發布消息,設備收到消息后即可進行一系列操作。

二進制格式實現

MQTT基于二進制實現而不是字符串,比如HTTP和XMPP都是基于字符串實現。由于HTTP和XMPP擁有冗長的協議頭部,而MQTT固定報文頭僅有兩字節,所以相比其他協議,發送一條消息最省流量。

MQTT的安全

由于MQTT運行于TCP層之上并以明文方式傳輸,這就相當于HTTP的明文傳輸,使用Wireshark可以完全看到MQTT發送的所有消息,消息指令一覽無遺,如下圖所示:

這樣可能會產生以下風險:

  • 設備可能會被盜用;
  • 客戶端和服務端的靜態數據可能是可訪問的(可能會被修改);
  • 協議行為可能有副作用(如計時器攻擊);
  • 拒絕服務攻擊;
  • 通信可能會被攔截、修改、重定向或者泄露;
  • 虛假控制報文注入。

作為傳輸協議,MQTT僅關注消息傳輸,提供合適的安全功能是開發者的責任。安全功能可以從三個層次來考慮——應用層、傳輸層、網絡層。

  • 應用層:在應用層上,MQTT提供了客戶標識(Client Identifier)以及用戶名和密碼,可以在應用層驗證設備。
  • 傳輸層:類似于HTTPS,MQTT基于TCP連接,也可以加上一層TLS,傳輸層使用TLS加密是確保安全的一個好手段,可以防止中間人攻擊。客戶端證書不但可以作為設備的身份憑證,還可以用來驗證設備。
  • 網絡層:如果有條件的話,可以通過拉專線或者使用VPN來連接設備與MQTT代理,以提高網絡傳輸的安全性。

認證

MQTT支持兩種層次的認證:

  • 應用層:MQTT支持客戶標識、用戶名和密碼認證;
  • 傳輸層:傳輸層可以使用TLS,除了加密通訊,還可以使用X509證書來認證設備。

客戶標識

MQTT客戶端可以發送最多65535個字符作為客戶標識(Client Identifier),一般來說可以使用嵌入式芯片的MAC地址或者芯片序列號。雖然使用客戶標識來認證可能不可靠,但是在某些封閉環境或許已經足夠了。

用戶名和密碼

MQTT協議支持通過CONNECT消息的username和password字段發送用戶名和密碼。

用戶名及密碼的認證使用起來非常方便,不過由于它們是以明文形式傳輸,所以使用抓包工具就可以輕易的獲取。

一般來說,使用客戶標識、用戶名和密碼已經足夠了,比如支持MQTT協議連接的OneNET云平臺,就是使用了這三個字段作為認證。如果感覺還不夠安全,還可以在傳輸層進行認證。

在傳輸層認證

在傳輸層認證是這樣的:MQTT代理在TLS握手成功之后可以繼續發送客戶端的X509證書來認證設備,如果設備不合法便可以中斷連接。

使用X509認證的好處是,在傳輸層就可以驗證設備的合法性,在發送CONNECT消息之前便可以阻隔非法設備的連接,以節省后續不必要的資源浪費。而且,MQTT協議運行在使用TLS時,除了提供身份認證,還可以確保消息的完整性和保密性。

選擇用戶數據格式

MQTT協議只實現了傳送消息的格式,并沒有限制用戶協議需要按照一定的風格,因此在MQTT協議之上,我們需要定義一套自己的通信協議。

比如說,發布者向設備發布一條打開消息,設備可以回復一個消息并攜帶返回碼,這樣的消息格式是使用二進制、字符串還是JSON格式呢?下面就簡單做個選型參考。

十六進制/二進制

MQTT原本就是基于二進制實現的,所以用戶協議使用二進制實現是一個不錯的選擇。雖然失去了直觀的可讀性,但可以將流量控制在非常小。

其實對于單片機開發者來說十六進制并不陌生,因為單片機寄存器都是以位來操作的,芯片間通信也會使用十六進制/二進制。而對于沒有單片機開發經驗的工程師來說,十六進制/二進制可能就太原始了。下面我們繼續看看還有沒有其他方案。

字符串

對單片機開發者來說,字符串也是一個選擇。比如通過串口傳輸的AT指令就是基于字符串通信的。使用字符串方便了人閱讀,但是對高級語言開發者來說,字符串依舊不是最佳選擇,恐怕鍵值對(Key-Value)才是最優形式。

JSON

JSON中文全稱是JavaScript對象標記語言,在這門語言中,一切都是對象。因此,任何支持的類型都可以通過JSON來表示,例如字符串、數字、對象、數組等。其語法規則是:

  • 對象表示為鍵值對;
  • 數據由逗號分隔;
  • 花括號保存對象;
  • 方括號保存數組。

JSON層次結構簡潔清晰,易于閱讀和編寫,同時也易于機器解析和生成,有效提升網絡傳輸效率。

對于單片機開發者,主流的微控制器軟件開發工具Keil有提供JSON庫,可以用于STC、STM32等微控制器開發,所以在微控制器上解析JSON不需要自己寫一個JSON解析器或者移植了。

如果實在懶得使用JSON庫生成或解析,也可以直接使用C語言中的sprintf生成JSON字符串,比如:

sprintf(buf, "{\"String\":\"%s\", \"Value\":%d}", "Hello World!", 12345);

這樣就可以生成一個{“String”:”Hello World!”, “Value”:12345}JSON字符串了。

XML

MQTT協議只負責通信部分,用戶協議可以自己選擇,當然也可以選擇復雜又冗長的XML格式。可是既然要選擇MQTT+XML,為什么不考慮換為XMPP呢?

小結

綜上所述,MQTT+JSON是目前最優方案。協議簡潔清晰、易于閱讀、解析和生成等,也考慮了服務器端開發者和設備端開發者的開發成本。

有關MQTT的云平臺和工具

支持MQTT的云平臺

目前,百度、阿里、騰訊的云平臺都有了物聯網開發套件。除了BAT三大家,下面再介紹一些其他支持MQTT的物聯網云平臺。

  • OneNET云平臺:OneNET是由中國移動打造的PaaS物聯網開放平臺。平臺能夠幫助開發者輕松實現設備接入與設備連接,快速完成產品開發部署,為智能硬件、智能家居產品提供完善的物聯網解決方案。OneNET云平臺已經于2014年10月正式上線。
  • 云巴:云巴(Cloud Bus)是一個跨平臺的雙向實時通信系統,為物聯網、App和Web提供實時通信服務。云巴基于MQTT,支持Socket.IO協議,支持RESTful API。

MQTT服務器

如果不想使用云平臺,只是純粹地玩一下MQTT,或者只想在內網對設備進行監控,那么可以自己本地部署一個MQTT服務器。下面介紹幾款MQTT服務器:

  • Apache-Apollo:一個代理服務器,在ActiveMQ基礎上發展而來,可以支持STOMP、AMQP、MQTT、Openwire、SSL和WebSockets等多種協議,并且Apollo提供后臺管理頁面,方便開發者管理和調試。
  • EMQ:EMQ 2.0,號稱百萬級開源MQTT消息服務器,基于Erlang/OTP語言平臺開發,支持大規模連接和分布式集群,發布訂閱模式的開源MQTT消息服務器。
  • HiveMQ:一個企業級的MQTT代理,主要用于企業和新興的機器到機器M2M通訊和內部傳輸,最大程度的滿足可伸縮性、易管理和安全特性,提供免費的個人版。HiveMQ提供了開源的插件開發包。
  • Mosquitto:一款實現了消息推送協議MQTT v3.1的開源消息代理軟件,提供輕量級的、支持可發布/可訂閱的消息推送模式。

MQTT調試工具

知道了各大平臺的MQTT,同時自己也可以在內網部署MQTT服務器,那接下來沒有調試工具怎么行呢,難道要用自己喜歡的語言編寫一個?當然不需要。

MQTT調試工具可以考慮使用HiveMQ的MQTT客戶端——HiveMQ Websockets Client,這是一款基于WebSocket的瀏覽器MQTT客戶端,支持主題訂閱和發布。

MQTT與其他協議

目前各大平臺都開始支持MQTT協議,MQTT相比其他協議有什么優勢呢?物聯網設備能不能用其他的協議呢?下面是MQTT與其他部分協議的比較,給大家作為參考。

MQTT與TCP Socket

雖然MQTT運行于TCP層之上,看起來這兩者之間根本沒有比較性,但筆者覺得還是有必要敘述一番,因為大多數從事硬件或嵌入式開發的工程師,都是直接在TCP層上通信的。

從事嵌入式開發工作的人都應該知道LwIP,LwIP是一套用于嵌入式系統的開放源代碼TCP/IP協議棧,LwIP在保證嵌入式產品擁有完整的TCP/IP功能的同時,又能保證協議棧對處理器資源的有限消耗,其運行一般僅需要幾十KB的RAM和40KB左右的ROM。

也就是說,只要是嵌入式產品使用了LwIP,就支持TCP/IP協議棧,進而可以使用MQTT協議。

由于TCP協議有粘包和分包問題,所以傳輸數據時需要自定義協議,如果傳輸的數據報超過MSS(最大報文段長度),一定要給協議定義一個消息長度字段,確保接收端能通過緩沖完整收取消息。一個簡單的協議定義:消息頭部+消息長度+消息正文。

當然,使用MQTT協議則不需要考慮這個問題,這些MQTT都已經處理好了,MQTT最長可以一次性發送256MB數據,不用考慮粘包分包的問題。

總之,TCP和MQTT本身并不矛盾,只不過基于Socket開發需要處理更多的事情,而且大多數嵌入式開發模塊本身也只會提供Socket接口供廠家自定義協議。

MQTT與HTTP

HTTP最初的目的是提供一種發布和接收HTML頁面的方法,主要用于Web。HTTP是典型的C/S通訊模式:請求從客戶端發出,服務端只能被動接收,一條連接只能發送一次請求,獲取響應后就斷開連接。

該協議最早是為了適用Web瀏覽器的上網瀏覽場景而設計的,目前在PC、手機、Pad等終端上都應用廣泛。由于這樣的通信特點,HTTP技術在物聯網設備中很難實現設備的反向控制,不過非要實現也不是不行,下面看一下Web端的例子。

目前,在微博等SNS網站上有海量用戶公開發布的內容,當發布者發布消息,數據傳到服務器更新時,就需要給關注者盡可能的實時更新內容。Web網站基于HTTP協議,使用HTTP協議探測服務器上是否有內容更新,就必須頻繁地讓客戶端請求服務器進行確認。

在瀏覽器中要實現這種效果,可以使用Comet技術,Comet是基于HTTP長連接的“服務器推”技術,主要有兩種實現模型:基于AJAX的長輪詢(long-polling)方式和基于Iframe及htmlfile的流(streaming)方式。這兩種技術模型在這里不詳細展開,有興趣的讀者可以查閱相關資料。

如果要實現設備的反向控制,可能就要用到前面提到的Comet技術。由于需要不斷的請求服務器,會導致通信開銷非常大,加上HTTP冗長的報文頭,在節省流量上實在沒有優勢。

當然,如果只是單純地讓設備定時上報數據而不做控制,也是可以使用HTTP協議的。

MQTT與XMPP

最有可能與MQTT競爭的是XMPP協議。XMPP(可擴展通訊與表示協議)是一項用于實時通訊的開放技術,它使用可擴展標記語言(XML)作為交換信息的基本格式。其優點是協議成熟、強大、可擴展性強。目前主要應用于許多聊天系統中,在消息推送領域,MQTT和XMPP互相競爭。下面列舉MQTT與XMPP各自的特性:

  • XMPP協議基于繁重的XML,報文體積大且交互繁瑣;而MQTT協議固定報頭只有兩個字節,報文體積小、編解碼容易;
  • XMPP基于JID的點對點消息傳輸;MQTT協議基于主題(Topic)發布\訂閱模式,消息路由更為靈活;
  • XMPP協議采用XML承載報文,二進制必須進行Base64編碼或其他方式處理;MQTT協議未定義報文內容格式,可以承載JSON、二進制等不同類型報文,開發者可以針對性的定義報文格式;
  • MQTT協議支持消息收發確認和QoS保證,有更好的消息可靠性保證;而XMPP主協議并未定義類似機制;
  • 在嵌入式設備開發中大多使用的是C語言開發,C語言解析XML是非常困難的。MQTT基于二進制實現且未定義報文內容格式,可以很好的兼顧嵌入式C語言開發者;而XMPP基于XML,開發者需要配合協議格式,不能靈活開發。

綜上所述,在嵌入式設備中,由于需要一個靈巧簡潔,對設備開發者和服務端開發者都友好的協議,MQTT比XMPP更具有優勢。

MQTT與CoAP

CoAP也是一個能與MQTT競爭的協議。其模仿HTTP的REST模型,服務端以URI方式創建資源,客戶端可以通過GET、PUT、POST、DELETE方式訪問這些資源,并且協議風格也和HTTP極為相似,例如一個設備有溫度數據,那么這個溫度可以被描述為:

不過,如果使用CoAP可能會讓物聯網后臺的情況變得復雜,比如MQTT可以實現一個最簡單的IoT架構:Device + MQTT服務器 + APP,手機端或Web端可以直接從MQTT服務器訂閱想要的主題。而CoAP可能需要這樣的架構:CoAP + Web + DataBase + App,使用CoAP必須經過DataBase才能轉給第三方。

至于CoAP和MQTT孰優孰劣,這里不作定論。不過目前來說,CoAP資料還是略少。而且,MQTT除了可以應用于物聯網領域,在手機消息推送、在線聊天等領域都可以有所作為。

小結

經過以上的比較,我們可以得出如下結論:MQTT基于異步發布/訂閱的實現解耦了消息發布者和訂閱者,基于二進制的實現節省了存儲空間及流量,同時MQTT擁有更好的消息處理機制,可以替代TCP Socket一部分應用場景。

相對于HTTP和XMPP,MQTT可以選擇用戶數據格式,解析復雜度低,同時MQTT也可用于手機推送等領域。手機作為與人連接的入口,正好建立了人與物的連接,可謂一箭雙雕。

當然,其他協議也可以作為一個輔助的存在,HTTP可以為只需定時上傳數據的設備服務,CoAP則更適用于非常受限的移動通信網絡,表3直觀地展示了上文提到的幾種協議之間的優劣異同。

結語

最后,讓我們把視角轉向各大互聯網公司云平臺。目前,阿里、百度、騰訊都把MQTT協議作為物聯網前置接入套件單獨列出來,作為標準云服務提供,物聯網云端套件對MQTT的支持日趨完善。設備端開發者只需根據平臺提供的MQTT接口和文檔即可把設備接入互聯網,從而實現人與物的連接。由此可以認為,MQTT極有可能成為物聯網時代的頭號協議。

總結

以上是生活随笔為你收集整理的物联网 | 管中窥豹,一线工程师看MQTT的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。