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

歡迎訪問 生活随笔!

生活随笔

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

c/c++

MQTT协议通俗讲解

發布時間:2025/3/21 c/c++ 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MQTT协议通俗讲解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

參考 Reference

v3.1.1

  • 英文原版
  • 中文翻譯版

其他資源

網站

  • MQTT官方主頁
  • Eclipse Paho 項目主頁

測試工具

  • MQTT Spy(基于JDK)
  • Chrome插件 MQTTLens(需FQ)

基本概念 Basic Conception

Session 會話

定義

  • 定義:某個客戶端(由ClientID作為標識)和某個服務器之間的邏輯層面的通信
  • 生命周期(存在時間):會話 >= 網絡連接

ClientID

  • 客戶端唯一標識,服務端用于關聯一個Session
  • 只能包含這些?大寫字母,小寫字母 和 數字(0-9a-zA-Z),23個字符以內
  • 如果 ClientID 在多次 TCP連接中保持一致,客戶端和服務器端會保留會話信息(Session)
  • 同一時間內 Server 和同一個 ClientID 只能保持一個 TCP 連接,再次連接會踢掉前一個

CleanSession 標記

  • 在Connect時,由客戶端設置?
  • 0 —— 開啟會話重用機制。網絡斷開重連后,恢復之前的Session信息。需要客戶端和服務器有相關Session持久化機制。
  • 1 —— 關閉會話重用機制。每次Connect都是一個新Session,會話僅持續和網絡連接同樣長的時間。

客戶端 Session

  • 已經發送給服務端,但是還沒有完成確認的 QoS 1 和 QoS 2 級別的消息?
  • 已從服務端接收,但是還沒有完成確認的 QoS 2 級別的消息

服務器端 Session

  • 會話是否存在,即使會話狀態的其它部分都是空? (SessionFlag)
  • 客戶端的訂閱信息? (ClientSubcription)
  • 已經發送給客戶端,但是還沒有完成確認的 QoS 1 和 QoS 2 級別的消息
  • 即將傳輸給客戶端的 QoS 1 和 QoS 2 級別的消息
  • 已從客戶端接收,但是還沒有完成確認的 QoS 2 級別的消息
  • (可選)準備發送給客戶端的 QoS 0 級別的消息

長連接維護與管理

Keep Alive 心跳

  • 目的是保持長連接的可靠性,以及雙方對彼此是否在線的確認。
  • 客戶端在Connect的時候設置 Keep Alive 時長。如果服務端在 1.5 * KeepAlive 時間內沒有收到客戶端的報文,它必須斷開客戶端的網絡連接
  • Keep Alive 的值由具體應用指定,一般是幾分鐘。允許的最大值是 18 小時 12 分 15 秒

Will 遺囑

  • 遺囑消息(Will Message)存儲在服務端,當網絡連接關閉時,服務端必須發布這個遺囑消息,所以被形象地稱之為遺囑,可用于通知異常斷線。
  • 客戶端發送 DISCONNECT 關閉鏈接,遺囑失效并刪除
  • 遺囑消息發布的條件,包括:?
  • 服務端檢測到了一個 I/O 錯誤或者網絡故障
  • 客戶端在保持連接(Keep Alive)的時間內未能通訊
  • 客戶端沒有先發送 DISCONNECT 報文直接關閉了網絡連接
  • 由于協議錯誤服務端關閉了網絡連接
  • 相關設置項,需要在Connect時,由客戶端指定
  • Will Flag —— 遺囑的總開關
  • 0 -- 關閉遺囑功能,Will QoS 和 Will Retain 必須為 0
  • 1 --? 開啟遺囑功能,需要設置?Will Retain?和?Will QoS
  • Will QoS —— 遺囑消息 QoS
  • 可取值 0、1、2,含義與消息QoS相同
  • Will Retain —— 遺囑是否保留
  • 0 -- 遺囑消息不保留,后面再訂閱不會收到消息
  • 1 -- 遺囑消息保留,持久存儲
  • Will Topic —— 遺囑話題
  • Will Payload —— 遺囑消息內容

消息基本概念

報文標識 Packet?Identifier?????????????????????????????????????????????????????

  • 存在報文的可變報頭部分,非零兩個字節整數 (0-65535]
  • 一個流程中重復:這些報文包含 PacketID,而且在一次通信流程內保持一致:
  • PUBLISH(QoS>0?時),PUBACK,PUBREC,PUBREL,PUBCOMP
  • SUBSCRIBE,??SUBACK
  • UNSUBSCIBE,UNSUBACK????????????????????????????????????????
  • 新的不重復:客戶端每次發送一個新的這些類型的報文時都必須分配一個當前 未使用的PacketID
  • 當客戶端處理完這個報文對應的確認后,這個報文標識符就釋放可重用。
  • 獨立維護:客戶端和服務端彼此獨立地分配報文標識符。因此,客戶端服務端組合使用相同的報文標識符可以實現?并發?的消息交換。可能出現一下情況,并不算異常:

Payload 有效載荷,消息體

  • 最大允許 256MB
  • Publish 的 Payload 允許為空。在很多場合下,代表將持久消息(或者遺囑消息)清空。
  • UTF-8編碼

Retain 持久消息(粘性消息)

  • RETAIN 標記:每個Publish消息都需要指定的標記
  • 0 ——?服務端不能存儲這個消息,也不能移除或替換任何 現存的保留消息???????????????
  • 1 ——?服務端必須存儲這個應用消息和它的QoS等級,以便它可以被分發給未來的訂閱者?
  • 每個Topic只會保留最多一個 Retain 持久消息
  • 客戶端訂閱帶有持久消息的Topic,會立即受到這條消息
  • 服務器可以選擇丟棄持久消息,比如內存或者存儲吃緊的時候
  • 如果客戶端想要刪除某個Topic 上面的持久消息,可以向這個Topic發送一個Payload為空的持久消息
  • 遺囑消息(Will)的Retain持久機制同理

QoS 服務等級(消息可靠性)

最多一次 At most Once(QoS == 0)

  • 沒有回復,不需要存儲。有可能丟失(網絡異常斷開,業務層繁忙或者錯誤)

至少一次 At least Once(QoS == 1?)

  • 發送者S 發送前需要做持久化存儲,接受者R 不需要持久化存儲
  • 如果 發送者S 沒有收到 接收者R 的回復 PUBACK,過一段時間 發送者S 會重新發送,DUP標記為1(在同一Session內)。
  • 接受者R 發送 PUBACK 后,不需要知道對方是否收到,馬上把消息交給上層業務。如果此時網絡異常,會導致發送者重發。這樣接受者收到多個消息(所以叫至少一次)。

有且僅有一次 Exactly Once(QoS == 2 )

  • 發送者S 發送 PUBLISH 前,需要做持久化存儲。接受者R 回復PUBREC 后,也需要做持久化存儲
  • 如果 發送者S 沒有收到 接收者R 的回復 PUBREC,過一段時間 發送者S 會重新發送,DUP標記為1(在同一Session內)。
  • 如果 接受者R 沒有收到 發送者S 的回復 PUBREL,過一段時間 接受者R 會重新發送PUBREC。
  • 發送者S 收到 PUBREC后,刪除持久化消息,但是要保存 PacketID
  • 接收者R 受到 PUBREL后,刪除持久化PUBREC。然后將消息發給上層,同時回復 PUBCOMP。
  • 發送者S 收到 PUBCOMP 后,刪除 PacketID,通信完美結束。
  • 這套流程可以?嚴格保證 一個包不管在什么情況下 接收者R 只收到一次 。

重傳標記 DUP 與重傳機制 (QoS > 0)

  • 如果客戶端或者服務器發送了一個 Publish 消息,一段時間內沒收到 PublishAck 回復,則認為消息丟失,進行重傳。
  • 在一個Session內,進行重傳的時候,頭部的?DUP 重傳標志 設置為1。
  • 客戶端有可能收到?DUP == 0 的重傳包(Payload相同,PacketID不同)。因為可能因為網絡問題,下次重傳時間較久,Session已經釋放,PacketID 已經變更。
  • 客戶端發給服務器的和服務器轉發給別的客戶端的 Publish 消息,DUP 重傳標志不會傳遞
  • 接收者收到一個?DUP 標志為 1 的控制報文時,并不能保證之前收到過相同的報文

消息重傳順序????????????????????????????????????

  • 重發任何之前的?PUBLISH?報文時,必須按原始?PUBLISH?報文的發送順序重發?(適用于QoS 1?和?QoS 2?消息)
  • 必須按照對應的?PUBLISH?報文的順序發送?PUBACK?報文?(QoS 1?消息)
  • 必須按照對應的?PUBLISH?報文的順序發送?PUBREC?報文?(QoS 2?消息)
  • 必須按照對應的?PUBREC?報文的順序發送?PUBREL?報文?(QoS 2?消息)
  • QoS == 1 時,雖然是PUBLISH有序的,但是可能會重復。例如,發布者按順序?1,2,3,4?發送消息,訂閱者收到的順序可能是?1,2,3,2,3,4。?
  • QoS == 1 時,如果限制?傳輸窗口 (in-flight window)?==1,即同一時刻只有一個包在傳輸,就可以保證亂序。例如,訂閱者收到的順序可能是?1,2,3,3,4,而不是?1,2,3,2,3,4?
  • QoS == 2 時,肯定不會存在亂序的問題。

?

話題 與訂閱機制??Topic & Subcribe

Topic 話題 和?TopicFilter 話題過濾器

  • Pub-Sub消息模型的核心機制
  • UTF-8?編碼字符串,不能超過?65535?字節。層級數量沒有限制
  • 不能包含任何的下文中提到的特殊符號(/、+、#),必須至少包含一個字符??
  • 區分大小寫,可以包含空格,不能包含空字符?(Unicode U+0000)??
  • 在收部或尾部增加 斜杠?“/”,會產生不同的Topic和TopicFilter。舉例:
  • “/A”?和?“A”?是不同的
  • “A” 和 “A/” 是不同的
  • 只包含斜杠?“/”?的?Topic?或?TopicFilter?是合法的???????????????????????????????????????????????????????????

TopicFilter中的特殊符號

  • 層級分隔符?/
  • 用于分割主題的每個層級,為主題名提供一個分層結構???????
  • 主題層級分隔符可以出現在 Topic 或 TopicFilter 的任何位置???????????????????????????
  • 特例:相鄰的主題層次分隔符表示一個零長度的主題層級?????????
  • 單層通配符 +
  • 只能用于單個主題層級匹配的通配符。例如,“a/b/+” 匹配 “a/b/c1” 和 “a/b/c2” ,但是不匹配 “a/b/c/d”??????
  • 可以匹配?任意層級,包括第一個和最后一個層級。例如,“+”?是有效的,“sport/+/player1”?也是有效的。
  • 可以在多個層級中使用它,也可以和多層通配符一起使用。?例如,“+/tennis/#”?是有效的。????????????????
  • 只能匹配本級不能匹配上級。例如,“sport/+”?不匹配?“sport”?但是卻匹配“sport/”,“/finance”?匹配?“+/+”?和?“/+”?,但是不匹配?“+”。?
  • 多層通配符 #
  • 用于匹配主題中任意層級的通配符
  • 匹配包含本身的層級和子層級。例如?“a/b/c/#" 可以匹配 “a/b/c”、“a/b/c/d”?和??“a/b/c/d/e”
  • 必須是最后的結尾。例如“sport/tennis/#/ranking”是無效的??????
  • “#”是有效的,會收到所有的應用消息。?(服務器端應將此類 TopicFilter禁掉 )

以$開頭的,服務器保留

  • 服務端不能將 $ 字符開頭的 Topic 匹配通配符 (#或+) 開頭的 TopicFilter
  • 服務端應該阻止客戶端使用這種 Topic 與其它客戶端交換消息。服務端實現可以將 $ 開頭的主題名用作其他目的。
  • $SYS/?被廣泛用作包含服務器特定信息或控制接口的主題的前綴
  • 客戶端不特意訂閱 $開頭的 Topic,就不會收到對應的消息
  • 訂閱 “#” 的客戶端不會收到任何發布到以 “$” 開頭主題的消息
  • 訂閱 “+/A/B” 的客戶端不會收到任何發布到 “$SYS/A/B” 的消息
  • 訂閱 “$SYS/#” 的客戶端會收到發布到以 “$SYS/” 開頭主題的消息
  • 訂閱 “$SYS/A/+” 的客戶端會收到發布到 “$SYS/A/B” 主題的消息
  • 如果客戶端想同時接受以 “$SYS/” 開頭主題的消息和不以 $ 開頭主題的消息,它需要同時 訂閱 “#” 和 “$SYS/#”

訂閱?Subscribe??與 QoS降級

  • 訂閱機制基于TopicFilter匹配
  • 一個Subsribe請求?可訂閱多個?Topic(節省帶寬,多訂閱盡量用一次請求)。取消訂閱也同理
  • 每一個訂閱需要指定一個QoS,指定了客戶端接收消息所允許的最大QoS級別。但是服務器端最終授權返回的QoS可能會小于等于客戶端請求的QoS
  • 對于高于QoS的消息(比如說訂閱的QoS限制到1,消息的QoS指定到2),那么客戶端會收到一個QoS降低為指定的?限制QoS 的消息(消息的QoS降為1,不保證只收到一次)
  • 訂閱關系可以被覆蓋,以TopicFilter為標識。如果后面訂閱一個相同的TopicFilter,但是指定的QoS不同,則以后面的為準,QoS升高后,重發相應等級的 Retain 消息

安全傳輸與鑒權認證? Security & Certification

傳輸層

  • 可以采用 TCP、SSL/TLS?[RFC5246]?、WebSocket?作為傳輸層。UDP不可以,因為不保證可靠傳輸與有序傳輸。
  • 服務器端返回的數據極有可能出現?粘包 的情況。客戶端經常會在連接建立之后,連續調用多個訂閱,這樣服務器端就會回復多個訂閱ACK包,同時還有各個Topic上的持久消息,一般粘成一個TCP包返回過來
  • 端口(IANA分發)
  • 1883:over TCP,無加密
  • 8883:over SSL/TLS,單向認證(強烈建議)
  • 8884:over SSL/TLS,雙向認證
  • 8080:over WebSockets,未加密
  • 8081:over WebSockets,加密??????????????????????????????????????????????????
  • 可使用SOCKS代理,可利用安全隧道(如SSH)

潛在的風險與應對機制

  • 潛在風險
  • 設備可能會被盜用
  • 客戶端和服務端的靜態數據可以被訪問(比如客戶端Root導致數據泄露、服務器被拖庫)
  • 協議規定的行為可能有副作用 (如計時器攻擊? “timing attacks”)
  • 拒絕服務攻擊(DoS)
  • 通信可能會被攔截、修改、重定向或者泄露(抓包、中間人)
  • 虛假控制報文注入
  • 應對的機制
  • 用戶和設備身份認證
  • 服務端資源訪問授權
  • 控制報文和 Payload 的完整性校驗
  • 控制報文和 Payload 的隱私控制

客戶端身份驗證與授權? (Authentication & Authorization of Client)

  • 用戶名+密碼驗證:Connect 登錄的時候,傳入 UserName 和 Password
  • 相關標記位:在Connect時,由客戶端設置
  • 用戶名(UserName Flag)標記設置為1,才可以穿入
  • 密碼(Password Flag)標記設置為1
  • 外部驗證:LDAP、OAuth 或者 操作系統的認證機制
  • 用戶名密碼加密:防止中間人攻擊和重放攻擊
  • 應用層:客戶端通過應用消息給服務端發送憑證用于身份驗證。
  • 授權:基于客戶端提供的信息如用戶名、客戶端標識符(ClientId)、客戶端的主機名或 IP 地址,或者身份認證的結果,服務端可以限制對某些服務端資源的訪問

服務端身份驗證 (Authentication of?Server?by Client)

  • MQTT 協議不是雙向信任的,它沒有提供客戶端驗證服務端身份的機制
  • TLS:客戶端可以使用服務端發送的SSL證書驗證服務端的身份
  • 應用層:可以通過服務端給客戶端發送憑證用于身份驗證的應用層消息
  • VPN:在客戶端和服務端之間使用虛擬專用網(VPN)可以確保客戶端連接的是預期的服務器。

控制報文和 Payload 的完整性(Integrity)

  • TLS:提供了對網絡傳輸的數據做完整性校驗的哈希算法
  • 應用層:可以在應用消息中單獨包含哈希值。這樣做可以為 PUBLISH 控制報文的網絡傳輸和靜態數據提供內容的完整性檢查
  • VPN:在客戶端和服務端之間使用虛擬專用網(VPN)連接可以在 VPN 覆蓋的網絡段提供數據完整性檢查

控制報文和?Payload?的保密性(Privacy)

  • 輕量級加密:AES or DES,可適用于低端設備
  • TLS:可以對網絡傳輸的數據加密
  • 應用層:可以單獨加密 Payload 內容。這可以提供 Payload 傳輸途中和靜態數據的私密性。但不能給應用消息的其它屬性如 Topic 加密
  • 靜態數據加密:客戶端和服務端實現可以加密存儲靜態數據,例如可以將應用消息作為會話的一部分存儲
  • VPN:在客戶端和服務端之間使用虛擬專用網(VPN)連接可以在 VPN 覆蓋的網絡段保證數據的私密性

異常行為的檢測

  • 服務端實現可以監視客戶端的行為,檢測潛在的安全風險。例如:
  • 重復的連接請求
  • 重復的身份驗證請求
  • 連接的異常終止
  • 主題掃描 (請求發送或訂閱大量主題)
  • 發送無法送達的消息 (沒有訂閱者的主題)???
  • 客戶端連接但是不發送數據
  • 應對策略
  • 發現違反安全規則的行為,服務端實現可以斷開客戶端連接
  • 可以基于 IP地址 或 ClientID 實現一個?動態黑名單列表
  • 可以使用網絡層面的控制,實現基于 IP 地址或其它信息的?速率限制?或黑名單
  • 連接拒絕與錯誤碼

?

?

最佳實踐? Best Practice

客戶端 Client

選型?

  • Android
  • iOS
  • Javascript
  • PHP
  • Java

服務器端 Server

Broker選型

  • Mosquitto
  • ActiveMQ
  • RabbitMQ
  • HiveMQ
  • VerneMQ
  • EMQ
  • Apollo (from ActiveMQ)
  • RocketMQ
  • 商用版?
  • Mosca

Benchmark

  • Mosquitto + Apollo + Rabbit MQ + Mosca + VerneMQ?測評
  • RabbitMQ vs ActiveMQ?
  • RocketMQ vs Kafka(18項差異)
  • RocketMQ vs Kafka vs RabbitMQ 消息中間件的對比 —— 消息發送性能
  • 業界主流MQ對比

總結

以上是生活随笔為你收集整理的MQTT协议通俗讲解的全部內容,希望文章能夠幫你解決所遇到的問題。

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