因為工作需要,了解了一下MQTT。順便記下來,現在還不會用。
一、概述
MQTT(Message Queuing Telemetyr Transport 消息隊列遙測傳輸協議):基於發布/訂閱(Publish/Subscribe)模式的輕量級通訊協議,該協議構建於TCP/IP協議之上。
MQTT運行於TCP之上,屬於應用層協議。
二、MQTT消息格式
每條MQTT命令消息的消息頭都包含一個固定的報頭,有些消息會攜帶一個可變報文頭和一個負荷。消息格式如下:
固定報文頭|可變報文頭|負荷
1、 固定報文頭(Fixed Header)
最少有兩個字節,第一個字節包含消息的類型(Message Type)和QoS級別等標志位。第二個字節開始是剩余長度字節,該長度是后面的可變報文頭加消息負載的總長度,該字段最多允許四個字節。
剩余長度字段單個字節的最大值為0x7F. 也就是127個字節。MQTT協議規定,單個字節的最高位如果是1,表示后續還有字節存在,第八位起延續位的作用。
由於MQTT協議最多使用四個字節表示剩余長度,並且最后一個字節的最大值只能是0x7F,而不是0xFF。所以能發送的最大消息長度是256MB,而不是512MB。
2、 可變報文頭(Variable Header)
主要包含協議名,協議版本,連接標志,心跳間隔時間,連接返回碼,主題名等。
3、 有效負荷
實際上可以理解為消息的主體。當MQTT發送的消息類型是CONNECT(連接)、PUBLISH(發布)、SUBSCRIBE(訂閱)、SUBACK(訂閱確認)、UBSUNSCRIBE(取消訂閱)時會帶有負荷。
三、MQTT的主要特性
1、MQTT的消息類型
固定報文頭中的第一個字節包含連接標志,連接標志用來區分MQTT的消息類型。MQTT協議擁有14中不同的消息類型。如下圖:
可簡單分為連接及終止、發布和訂閱、Qos2消息的機制以及各種確認ACK。
2、消息質量(QoS)
MQTT消息質量有三個等級,QoS 0、Qos 1、Qos 2。
Qos 0:最多分發一次,消息的傳遞完全依賴底層的TCP/IP網絡,協議里沒有定義應答和重試。消息只會到達服務端一次,要么就沒到達。
Qos 1:至少分發一次、服務器的消息接收由PUBACK消息進行確認,如果通信鏈路或設備異常,或指定時間內沒有收到確認消息,發送端會重發這條在消息頭中設置了Dup位的消息。
Qos 2:只分發一次。最高級別的消息傳遞,消息丟失和重復都是不可接受的,使用這個服務質量等級會有額外的開銷。
3、遺願標志(Will Flag)
在可變報文頭的連接標志位字段(Connect Flags)里面有三個will標志位:Will Flag Will Qos和Retain Flag。這些will字段用於監控客戶端與服務器之間的連接狀況。
遺願消息:服務器與客戶端通信時,當遇到異常或客戶端心跳超時的情況,MQTT服務器會替客戶端發布一個will消息。當然如果服務器收到來自客戶端的DISCONNECT消息則不會觸發wiwll消息的發送。因此will字段可以應用於設備掉線后通知用戶的場景
4、 連接保活心跳機制(keep Alive Timer)
MQTT客戶端可以設置一個心跳間隔時間(keep Alive Timer),表示在每個心跳檢測時間內發送一條消息。如果在這個時間周期內,沒有業務數據相關的消息,客戶端會發送一個PINGREQ消息,相應的,服務器會返回一個PINGRESP消息進行確認。
如果服務器在一個半(1.5)個心跳間隔時間周期內沒有收到來自客戶端的消息,就會斷開與客戶端的連接。心跳間隔時間最大值可以設置為18個小時,8表示客戶端不會斷開。
四、MQTT其他特點
1、異步發布/訂閱實現
發布/訂閱模式解耦了發布消息的客戶(發布者)和訂閱消息的客戶(訂閱者)之間的關系。發布者與訂閱者並不需要直接建立聯系。
這個模式的好處有:
1) 發布者與訂閱者只需要知道同一個消息代理即可。
2) 發布者與訂閱者不需要直接交互,不需要同時在線。
2、二進制格式實現
MQTT基於二進制而不是字符串。固定報文頭僅有兩個字節,相比於其他協議(HTTPS 和XMPP都是基於字符串實現,有冗長的頭部),發送一條消息更省流量
3、MQTT的安全
由於MQTT運行於TCP層之上並且以明文傳輸,可以使用Wireshark看到MQTT發送的所有消息,消息指令一覽無遺。這會帶來一定的風險:
1) 設備可能會被盜用
2) 客戶端和服務端的靜態數據可能是可訪問的(可能會被修改)
3) 協議行為可能有副作用(如計時器攻擊)
4) 拒絕服務攻擊
5) 通信可能會被攔截 修改 重定向或者泄露
6) 虛假控制報文注入
作為傳輸協議,MQTT只關注消息傳輸,提供安全功能是開發者的責任。
4、認證
支持兩種層次的認證
1) 應用層:MQTT支持客戶標識,用戶名和密碼認證
客戶標識:MQTT客戶端可以發送最多65535個字符作為客戶標識,一般來說可以使用嵌入式芯片的MAC地址或芯片序列號。
用戶名和密碼:支持通過CONNECT消息的USERNAME和password字段發送用戶名和密碼。但是由於是用的明文傳輸,抓包工具很容易就獲取。
2) 傳輸層:傳輸層可以使用TLS,除了加密通訊,還可以使用X509證書來認證設備。
在傳輸層認證是這樣的:MQTT代理在TLS握手成功之后可以繼續發送客戶端的X509證書來認證設備,如果設備不合法就中斷連接。
5、 選擇用戶數據格式
MQTT協議只實現了傳送消息的格式,並沒有限制用戶協議需要按照特定風格。因此在MQTT協議之上,我們需要定義一套自己的通信協議。就可以有下面幾種選擇了、
1) 十六進制/二進制:
失去了可讀性,可以將流量控制的比較小。單片開發可能會比較喜歡用這個。
2) 字符串:
這個會方便閱讀。對於高級語言開發者來說,字符串依舊不是最佳選擇。鍵值對(Key-value)才是最優形式。
3) JSON:
在這門語言中,一切都是對象。因此任何支持的類型都可以通過JSON來表示。例如字符串、數字、對象、數組等、
語法規則是:對象表示鍵值對、數據用逗號分開、花括號保存對象、方括號保存數組。
JSON層次結構簡潔清晰,便於閱讀和編寫,易於機器解析和生成,有效提升網絡傳輸效率。
4) XML:
綜上,MQTT+JSON是最優解。
五、總結
MQTT基於異步發布/訂閱的實現解耦了消息發布者和訂閱者,基於二進制的實現節省了存儲空間及流量,同時擁有更好的消息處理機制。
MQTT協議是為大量計算能力有限,且工作在低帶寬、不可靠的網絡的遠程傳感器和控制設備通訊而設計的協議
以上 參考https://blog.csdn.net/anxianfeng55555/article/details/80908795
參考:https://www.cnblogs.com/zhangyu1024/p/6141818.html
補充幾個概念:
參考:https://www.jianshu.com/p/ecde412d2eeb
-
MQTT 客戶端
一個使用 MQTT 協議的設備、應用程序等,它總是建立到服務器的網絡連接。
-
可以發布信息,其他客戶端可以訂閱該信息
-
訂閱其它客戶端發布的消息
-
退訂或刪除應用程序的消息
-
斷開與服務器連接
-
-
MQTT 服務器
MQTT 服務器以稱為 Broker(消息代理),以是一個應用程序或一台設備。它是位於消息發布者 和訂閱者之間
- 接受來自客戶端的網絡連接
- 接受客戶端發布的應用信息
- 處理來自客戶端的訂閱和退訂請求
- 向訂閱的客戶轉發應用程序消息
-
主題(Topic)
連接到一個應用程序消息的標簽,該標簽與服務器的訂閱相匹配。服務器會將消息發送給訂閱所匹配標簽的每個客戶端。
-
要訂閱的主題。一個主題可以有多個級別,級別之間用斜杠字符分隔。例如,
/world
和emq/emqtt/emqx
是有效的主題。 -
訂閱者的Topic name支持通配符#和+ :
- # 支持一個主題內任意級別話題
- +只匹配一個主題級別的通配符
-
客戶端成功訂閱某個主題后,代理會返回一條 SUBACK 消息,其中包含一個或多個 returnCode 參數
-
-
主題篩選器(Topic Filter)
一個對主題名通配符篩選器,在訂閱表達式中使用,表示訂閱所匹配到的多個主題。
-
QoS(消息傳遞的服務質量水平)
服務質量,標志表明此主題范圍內的消息傳送到客戶端所需的一致程度。
- 值 0:不可靠,消息基本上僅傳送一次,如果當時客戶端不可用,則會丟失該消息。
- 值 1:消息應傳送至少 1 次。
- 值 2:消息僅傳送一次。
-
會話(Session)
每個客戶端與服務器建立連接后就是一個會話,客戶端和服務器之間有狀態交互。會話存在於一個網絡之間,也可能在客戶端和服務器之間跨越多個連續的網絡連接。
-
訂閱(Subscription)
訂閱包含主題篩選器(Topic Filter)和最大服務質量(QoS)。訂閱會與一個會話(Session)關聯。一個會話可以包含多個訂閱。每一個會話中的每個訂閱都有一個不同的主題篩選器。
- 客戶端在成功建立TCP連接之后,發送CONNECT消息,在得到服務器端授權允許建立彼此連接的CONNACK消息之后,客戶端會發送SUBSCRIBE消息,訂閱感興趣的Topic主題列表(至少一個主題)
- 訂閱的主題名稱采用UTF-8編碼,然后緊跟着對應的QoS值
-
發布(publish)
控制報文是指從客戶端向服務端或者服務端向客戶端傳輸一個應用消息,MQTT 客戶端發送消息請求,發送完成后返回應用程序線程
- 比如安卓的推送服務,還有一些即時通信軟件如微信等也是采用的推送技術。
-
負載(Payload)
消息訂閱者所具體接收的內容