MQTT協議從服務端到客戶端詳解

一:前言

       最近在瞭解MQTT協議相關的內容,內容有點多,特此把MQTT協議,以及其從服務端到客戶端的流程整理出來,記錄如下。

二:MQTT協議介紹

        MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通訊協議,它是一種輕量級的、基於代理的“發佈/訂閱”模式的消息傳輸協議。其具有協議簡潔小巧可擴展性強省流量省電等優點,而且已經有PHP,JAVA,Python,C,C#,Go等多個語言版本,基本可以使用在任何平臺上,幾乎可以把所有聯網物品和外部連接起來,所以特別適合用來當做物聯網的通信協議,實用的場景有遙感數據、汽車、智能家居、智慧城市、醫療醫護等等。

MQTT特點

        MQTT協議是爲大量計算能力有限,且工作在低帶寬不可靠的網絡的遠程傳感器和控制設備通訊而設計的協議,它具有以下主要的幾項特性:

1、使用發佈/訂閱消息模式,提供一對多的消息發佈,解除應用程序耦合;

2、對負載內容屏蔽的消息傳輸;

3、使用 TCP/IP 提供網絡連接;

4、有三種消息發佈服務質量:

        “至多一次”,消息發佈完全依賴底層 TCP/IP 網絡。會發生消息丟失或重複。這一級別可用於如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因爲不久後還會有第二次發送。

        “至少一次”,確保消息到達,但消息重複可能會發生。

        “只有一次”,確保消息到達一次。這一級別可用於如下情況,在計費系統中,消息重複或丟失會導致不正確的結果。

5、小型傳輸,開銷很小(固定長度的頭部是 2 字節),協議交換最小化,以降低網絡流量;

6、使用 Last Will (遺囑)和 Testament 特性通知有關各方客戶端異常中斷的機制;

MQTT協議內容

1 :消息模型

        MQTT是一種基於代理的發佈/訂閱的消息協議。與請求/回答這種同步模式不同,發佈/訂閱模式解耦了發佈消息的客戶(發佈者)與訂閱消息的客戶(訂閱者)之間的關係,這意味着發佈者和訂閱者之間並不需要直接建立聯繫。一個發佈者可以對應多個訂閱者,當發佈者發生變化的時候,他可以將消息一一通知給所有的訂閱者。這種模式提供了更大的網絡擴展性和更動態的網絡拓撲

       此外運用MQTT協議,設備可以很方便地連接到物聯網雲服務,管理設備並處理數據,最後應用到各種業務場景,如下圖所示

2 服務質量

        MQTT提供三種質量的服務:

         至多一次(qos = 0),可能會出現丟包的現象。使用在對實時性要求不高的情況。這一級別可應用於如下情景,如環境傳感器數據,丟失一次讀記錄無所謂,因爲很快下一次讀記錄就會產生。

        至少一次(qos = 1),保證包會到達目的地,但是可能出現重包。

        正好一次(qos = 2),保證包會到達目的地,且不會出現重包的現象。這一級別可用於如計費系統等場景,在計費系統中,消息丟失或重複可能會導致生成錯誤的費用。

服務質量

3 主題與通配符

        主題名稱(Topic name)用來標識已發佈消息的信息的渠道。訂閱者用它來確定接收到所關心的信息。它是一個分層的結構,用斜線“/”作爲分隔符(這個有點類似於restful風格)。主題還可以通過通配符進行過濾。其中,+可以過濾一個層級,而#只能出現在主題最後表示過濾任意級別的層級。值得注意的是MQTT允許使用通配符訂閱主題,但是並不允許使用通配符廣播

舉個例子:

building-b/floor-5:代表B樓5層的設備。

+/floor-5:代表任何一個樓的5層的設備。

building-b/#:代表B樓所有的設備。

4 遺囑

        當一個客戶端斷開連接的時候,它希望客戶端可以發送它指定的消息。該消息和普通消息的結構相同。通過設置該位並填入和信息相關的內容即可(後面會有介紹)。

5 消息類型

消息類型    類型    編碼說明

reserved       0        保留

connect        1         客戶端到服務端的連接請求

connACK     2          服務端對連接請求的響應

publish         3           發佈消息

puback         4           新發布消息確認,是QoS 1給PUBLISH消息的回覆

pubRec        5           QoS 2消息流的第一部分,表示消息發佈已記錄

pubRel          6           QoS 2消息流的第二部分,表示消息發佈已釋放

pubComp      7           QoS 2消息流的第三部分,表示消息發佈完

subscribe      8           客戶端訂閱某個主題

subBack        9           對於SUBSCRIBE消息的確認

unsubscribe 10           客戶端終止訂閱的消息

unsubBack   11       對於UNSUBSCRIBE消息的確認

pingReq        12       心跳

pingResp      13        確認心跳

disconnect    14        客戶端終止連接前通知MQTT代理

reserved        15        保留

MQTT協議頭部信息詳細介紹

        客戶端發佈消息經由服務器分發到所有對應的訂閱者那裏。一個訂閱者可以訂閱若干個主題(Topic name),但一個PUBLISH消息只能擁有一個主題。其消息架構如下:

1 固定頭部

        固定頭部,使用兩個字節,共16位:

Byte 1 消息類型和標誌字段,消息類型(4-7),使用4位二進制表示,可代表16種消息類型。

Byte 2 剩餘長度字段(至少1個字節,最多4個字節),採用big-endian模式存儲。

消息類型前面已有介紹 此處附上一張圖:

DUP flag(打開標誌)

保證消息可靠傳輸,默認爲0,只佔用一個字節,表示第一次發送。不能用於檢測消息重複發送等。適用於客戶端或服務器端嘗試重發PUBLISH(發送消息), PUBREL(QoS 2消息流的第二部分,表示消息發佈已釋放), SUBSCRIBE(客戶端訂閱某個主題) 或 UNSUBSCRIBE(客戶端終止訂閱的消息)消息,注意需要滿足以下條件:當 QoS > 0時消息需要回復確認,此時,在可變頭部需要包含消息ID。當值爲1時,表示當前消息先前已經被傳送過。

QoS(Quality of Service,服務質量)

使用兩個二進制表示PUBLISH類型消息:

RETAIN(保持)

僅針對PUBLISH消息。不同值,不同含義:

0:僅僅爲當前訂閱者推送此消息。

1:表示發送的消息需要一直持久保存(不受服務器重啓影響),不但要發送給當前的訂閱者,並且以後新來的訂閱了此Topic name的訂閱者會馬上得到推送。

另外對於新加入的訂閱者,只會取出最新的一個RETAIN flag = 1的消息推送。

Remaining Length(剩餘長度)

在當前消息中剩餘的byte(字節)數,包含可變頭部和負荷(稱之爲內容/body,更爲合適)。單個字節最大值:01111111,16進制:0x7F,10進製爲127。單個字節爲什麼不能是11111111(0xFF)呢?因爲MQTT協議規定,第八位(最高位)若爲1,則表示還有後續字節存在。

同時MQTT協議最多允許4個字節表示剩餘長度。那麼最大長度爲:0xFF,0xFF,0xFF,0x7F。

二進制表示爲:11111111,11111111,11111111,01111111

十進制:268435455 byte=261120KB=256MB=0.25GB

四個字節之間值的範圍:

2 可變頭部

        固定頭部僅定義了消息類型和一些標誌位,一些消息的元數據,需要放入可變頭部中。可變頭部內容字節長度 + Payload/負荷字節長度 = 剩餘長度,這個是需要牢記的。可變頭部,包含了協議名稱,版本號,連接標誌,用戶授權,心跳時間等內容,這些在後面會講到。

3 Payload/消息體/負荷

消息體主要是爲配合固定/可變頭部命令(比如CONNECT可變頭部User name標記若爲1則需要在消息體中附加用戶名稱字符串)而存在。

CONNECT/SUBSCRIBE/SUBACK/PUBLISH等消息有消息體。PUBLISH的消息體以二進制形式對待。

請記住MQTT協議只允許在PUBLISH類型消息體中使用自定義特性,在固定/可變頭部想加入自定義私有特性,就免了吧。這也是爲了協議免於流於形式,變得很分裂也爲了兼顧現有客戶端等。比如支持壓縮等,那就可以在Payload中定義數據支持,在應用中進行讀取處理

4 消息標識符/消息ID

        一個16位無符號位的short類型值(值不能爲 0,0做保留作爲無效的消息ID),僅僅要求在一個特定方向(服務器發往客戶端爲一個方向,客戶端發送到服務器端爲另一個方向)的通信消息中必須唯一。比如客戶端發往服務器,有可能存在服務器發往客戶端會同時存在重複,但不礙事。

可變頭部中,需要兩個字節的順序是MSB(Most Significant Bit) LSB(Last/Least Significant Bit),翻譯成中文就是,最高有效位,最低有效位。最高有效位在最低有效位左邊/上面,表示這是一個大端字節/網絡字節序,符合人的閱讀習慣,高位在最左邊。

MQTT協議連接和心跳介紹

 CONNECT

TCP連接建立完畢後,Client向Server發出一個Request。

如果一段時間內接收不到Server的Response,則關閉socket,重新建立一個session連接。

如果一個ClientID已經與服務器連接,則持有同樣ClientID的舊有連接必須由服務器關閉後,新建立才能建立。下面是一個較爲完整的CONNECT消息結構:

下面介紹Connect Flags相關的參數

1 連接標誌(Connect Flags)

一個字節表示,除了第1位是保留未使用,其它7位都具有不同含義。業務上很重要,對消息總體流程影響很大,需要牢記。

2 Clean Session

0,表示如果訂閱的客戶機斷線了,要保存爲其要推送的消息(QoS爲1和QoS爲2),若其重新連接時,需將這些消息推送(若客戶端長時間不連接,需要設置一個過期值)。 1,斷線服務器即清理相關信息,重新連接上來之後,會再次訂閱。

3 Will Flag

定義了客戶端(沒有主動發送DISCONNECT消息)出現網絡異常導致連接中斷的情況下,服務器需要做的一些措施。

簡而言之,就是客戶端預先定義好,在自己異常斷開的情況下,所留下的最後遺願(Last Will),也稱之爲遺囑(Testament)。 這個遺囑就是一個由客戶端預先定義好的主題和對應消息,附加在CONNECT的可變頭部中,在客戶端連接出現異常的情況下,由服務器主動發佈此消息。

只有在Will Flag位爲1時,Will Qos和Will Retain纔會被讀取,此時消息體payload中要出現Will Topic和Will Message具體內容,否則,Will QoS和Will Retain值會被忽略掉。

4 Will Qos

兩位表示,和PUBLISH消息固定頭部的QoS level含義一樣。這裏先略過,到PUBLISH消息再回過頭來看看,會更明白些。若標識了Will Flag值爲1,那麼Will QoS就會生效,否則會被忽略掉。

5 Will Retain

如果設置Will Flag,Will Retain標誌就是有效的,否則它將被忽略。當客戶端意外斷開服務器發佈其Will Message之後,服務器是否應該繼續保存。這個屬性和PUBLISH固定頭部的RETAIN標誌含義一樣,這裏先略過。

6 User name 和 password Flag

用於授權,兩者要麼爲0要麼爲1,否則都是無效。都爲0,表示客戶端可自由連接/訂閱,都爲1,表示連接/訂閱需要授權。

CONNACK

收到CONNECT消息之後,服務器應該返回一個CONNACK消息作爲響應:

若客戶端繞過CONNECT消息直接發送其它類型消息,服務器應關閉此非法連接 若客戶端發送CONNECT之後未收到CONNACT,需要關閉當前連接,然後重新連接

相同Client ID客戶端已連接到服務器,先前客戶端必須斷開連接後,服務器才能完成新的客戶端CONNECT連接 客戶端發送無效非法CONNECT消息,服務器需要關閉。

一個完整的CONNACK消息大致如下:

PUBLISH 發佈消息

  Client/Servier均可以進行PUBLISH。(這裏的server指的是MQTT的中間件服務,例如:下面會講到的Apollo,Mosquitto 等服務器)

  publish message 應該包含一個TopicName(Subject/Channel),即訂閱關鍵詞。

  具體的交互下面這張圖就描述的很清晰了:

PUBACK 發佈消息後的確認

QoS=1時,Server向Client發佈該確認(Client收到確認後刪除),訂閱者向Server發佈確認。PUBREC / PUBREL / PUBCOMP

QoS=2時

1. Server->Client發佈PUBREC(已收到);

2. Client->Server發佈PUBREL(已釋放);

3. Server->Client發佈PUBCOMP(已完成),Client刪除msg;訂閱者也會向Server發佈類似過程確認。

PUBREC字面意思爲Assured publish received,作爲訂閱者/服務器對QoS level = 2的發佈PUBLISH消息的發送方的響應,確認已經收到,爲QoS level = 2消息流的第二個消息。 和PUBACK相比,除了消息類型不同外,其它都是一樣

 PUBREL  Qos level = 2的協議流的第三個消息,有PUBLISH消息的發佈者發送,參與方接收。完整示範如下

 PUBCOMP  作爲QoS level = 2消息流第四個,也是最後一個消息,由收到PUBREL的一方向另一方做出的響應消息。完整的消息一覽,和PUBREL一致,除了消息類型。

PINGREQ / PINGRES 心跳

Client有責任發送KeepAliveTime時長告訴給Server(表明當前client處於活動狀態)。在一個時長內,發送PINGREQ,Server發送PINGRES確認。

Server在1.5個時長內未收到PINGREQ,就斷開連接。

Client在1個時長內未收到PINGRES,斷開連接。

一般來說,時長設置爲幾個分鐘。最大18小時,0表示一直未斷開。

心跳時間(Keep Alive timer)

以秒爲單位,定義服務器端從客戶端接收消息的最大時間間隔。一般應用服務會在業務層次檢測客戶端網絡是否連接,不是TCP/IP協議層面的心跳機制(比如開啓SOCKET的SO_KEEPALIVE選項)。 一般來講,在一個心跳間隔內,客戶端發送一個PINGREQ消息到服務器,服務器返回PINGRESP消息,完成一次心跳交互,繼而等待下一輪。若客戶端沒有收到心跳反饋,會關閉掉TCP/IP端口連接,離線。 16位兩個字節,可看做一個無符號的short類型值。最大值,2^16-1 = 65535秒 = 18小時。最小值可以爲0,表示客戶端不斷開。一般設爲幾分鐘,比如微信心跳週期爲300秒

連接異常中斷通知機制

CONNECT消息一旦設置在可變頭部設置了Will flag標記,那就啓用了Last-Will-And-Testament特性,此特性很贊。

一旦客戶端出現異常中斷,便會觸發服務器發佈Will Message消息到Will Topic主題上去,通知Will Topic訂閱者,對方因異常退出。

抓包分析頭部數據

前面說了這麼多都是概念性的東西,下面我來點實際性的操作,用wireshark抓包看看具體的MQTT協議數據到底長成什麼樣,加深對前面概念的理解

我這裏用的是wireshark+paho(gui)這兩個工具,borker使用的是mosquitto。順便提下paho是eclipse下的一個子項目,它只是一個庫,官網貌似並不提供gui版本(圖形界面),我這裏是從github上下載的源碼進行編譯得到的界面版本,這個界面對於MQTT的消息調試還是蠻好用的,有興趣的也可以試下,項目的github地址:https://github.com/eclipse/paho.mqtt.java

最新版的wireshark已經支持mqtt協議了,所以在過濾其裏面直接填入 mqtt 就可以過濾到mqtt協議的請求了

可以看到上面圖中已經抓到我在paho中發起建立連接的請求了,並且在info那一欄可以清楚的看到 connect command,我們再看下下面的具體數據包,它顯示的是原始是16進制的,10 1e 00 04 4d 51 54 54 04 02 00 3c 00 12 70 61 68 6f 31 31 31 35 37 37 32 31 39 34 33 36 30 33 這麼一大串,下面這張圖就解釋的比較清楚了

我們來分析下這個數據包,前面兩個字節是10和1e

第一個字節:0x10對應的2進制是 10000,用8位bit來顯示就是 0001 0000 ,上圖詳細的顯示了這8位的四個部分都是幹什麼用的,這裏就不再詳細介紹了

第二個字節:0x1e 表示剩餘長度,也就是說本次請求數據包中第二個字節後面所有的字節總數,0x1e換算成十進制就是1*16+14=30字節, “00 04 4d 51 54 54 04 02 00 3c 00 12 70 61 68 6f 31 31 31 35 37 37 32 31 39 34 33 36 30 33”

可變頭部,再次放圖如下:

三 :MQTT 服務端(實現MQTT協議的中間件)

MQTT協議服務端:https://github.com/mqtt/mqtt.github.io/wiki/servers

MQTT協議類庫(Client):https://github.com/mqtt/mqtt.github.io/wiki/libraries

MQTT協議官網:http://mqtt.org/

    MQTT協議有很多開源的broker可以用,這裏我整理了兩個,分別是Apollo和mosquito;詳細的服務端選擇可以去上面的服務端鏈接中選。以下所講的環境配置和服務器搭建都是在MAC環境上,其他平臺的可以參見選用broker的詳細文檔。

一:Apollo-Broker搭建

Apache Apollo是一個代理服務器,其是在ActiveMQ基礎上發展而來的,可以支持多種協議,如:STOMP、AMQP、MQTT、SSL等。其搭建流程如下:

1 配置JAVA_HOME,Apollo是java語言編寫的,因此搭建Apollo-Broker需要java環境,MAC下如何配置JAVA_HOME可自行查閱網上資料。

2下載Apollo

此處由於之針對自己macbook而言選擇OS X版本下載

將下載好的文件解壓到適當的目錄(最好單獨新建一個方便後續整理)。解壓後會有apache-apollo-xxx文件夾,該文件夾默認爲環境變量${APOLLO_HOME};

3 創建broker,有兩種方式

cd放置broker路徑(建議就放在2創建的文件夾中方便以後查看或整理)

方法一:通過環境變量 (相對路徑)創建${APOLLO_HOME}/bin/apollo create MyBroker //上面是通過環境變量直接創建,如果失敗說明之前操作有些問題導致環境變量配置失敗。

 方法二:將apollo拖入終端用絕對地址 創建 xxx/bin/apollo create MyBroker#在當前目錄下生成一個mqtt_test目錄,其下面包含:*****運行結果******* Creating apollo instance at: MyBroker Generating ssl keystore... You can now start the broker by executing:"/Users/lqx/Desktop/未命名文件夾/MyBroker/bin/apollo-broker"run Or you can run the brokerinthe background using:"/Users/lqx/Desktop/未命名文件夾/MyBroker/bin/apollo-broker-service"start

成功後文件目錄大致應該是這個樣子:

bin 運行腳本

etc 環境配置

data 存儲持久化數據

log 運行日誌

tmp 臨時文件

4 運行broker 

cd MyBroker(3創建的文件夾)

apollo-broker run

由於apollo提供了可視化web界面(這也就是我選擇他的原因),我們在瀏覽器中輸入

http://127.0.0.1:61680/(http訪問) 或者https://127.0.0.1:61681/(https訪問,可用於研究mqtt+ssl)輸入用戶名密碼即可登錄(默認用戶名:admin 密碼:password)

關於服務器與客戶端的聯調 ,我會在客戶端篇講到。

值得注意的是 默認配置的tcp的port是61613,我之前寫demo 的時候客戶端一直連不上broker,原因就是服務器所在主機的端口號61613沒打開,所以大家在搭建完服務器後一定要檢查相應的端口是否打開了,相應端口截圖如下

再說一下Mac的端口情況,目前OSX 10.10之前版本可以用以下指令開放端口

sudo ipfw add 61613 allow tcp from any to any dst-port 61613;

osx10.10之後的版本目前還沒找到開放端口的方法,有知道的可以告訴我一下,查閱資料得到的處理方式都是用Nginx服務器做端口轉發,不過比較麻煩,所以我用了一個簡單的方法替換了,方法如下:

Mac端默認的tcp端口開放了1883,這個大家可以在網絡實用工具中看,所以我們得去吧Apollobroker的配置文件中的tcpport 由61613改成1883,

在你上面創建好的broker文件夾中找到apollo.xml,這個就是配置文件

將tcp 配置port改成1883

然後重啓服務就可以了。其他系統可直接開放61613端口號,方便快捷。

apollo 除了提供了可視化Web界面外,還提供了測試網頁,

 

打開頁面如下

在連接後 可以去Apollo監控頁面(http://127.0.0.1:61680/(http訪問) 或者https://127.0.0.1:61681/(https訪問,可用於研究mqtt+ssl))查看,會發現有你連接的主題和消費者。

 

至此,Apollo 相關的服務器需要講得已經講完了。

二:mosquito 服務器搭建

Mosquitto是一款實現了 MQTT v3.1 協議的開源消息代理軟件,提供輕量級的,支持發佈/訂閱的的消息推送模式,使設備對設備之間的短消息通信簡單易用

Mosquitto是C語言實現的,不需要配置什麼環境,我們直接用homebrew安裝,簡單快捷。

1 打開終端 輸入brew install mosquitto直接安裝

Linux(ubuntu)環境下的安裝也比較簡單(注意#號,需要root權限):

# apt install mosquitto

當然如果真的是這麼安裝的,那麼不好意思,安裝的版本可能會比較低,不過也不要緊,照樣可以用。但是如果你想安裝最新版的,那麼就按照下面的命令來吧:

1、先刪除剛剛安裝mosquitto(沒有安裝的可以直接跳到第2步)

# apt-get --purge remove mosquitto

2、引入mosquitto倉庫並更新

# apt-add-repository ppa:mosquitto-dev/mosquitto-ppa

# apt-get update

3、安裝Mosquitto

# apt-get install mosquitto

4、檢查是否安裝成功

# service mosquitto status

安裝成功界面如下

mosquitto服務啓動命令

停止服務  brew services stop mosquitto

啓動服務  brew services start mosquitto

重啓服務  brew services restart mosquitto

接下來講一下mosquito的配置文件,配置文件是目錄/usr/local/etc/mosquitto/下的mosquitto.conf文件。配置文件相關說明如下,

# =================================================================    

# General configuration    

# =================================================================    

 

# 客戶端心跳的間隔時間    

#retry_interval 20    

 

# 系統狀態的刷新時間    

#sys_interval 10    

 

# 系統資源的回收時間,0表示儘快處理    

#store_clean_interval 10    

 

# 服務進程的PID    

#pid_file /var/run/mosquitto.pid    

 

# 服務進程的系統用戶    

#user mosquitto    

 

# 客戶端心跳消息的最大併發數    

#max_inflight_messages 10    

 

# 客戶端心跳消息緩存隊列    

#max_queued_messages 100    

 

# 用於設置客戶端長連接的過期時間,默認永不過期    

#persistent_client_expiration    

 

# =================================================================    

# Default listener    

# =================================================================    

 

# 服務綁定的IP地址    

#bind_address    

 

# 服務綁定的端口號    

#port 1883    

 

# 允許的最大連接數,-1表示沒有限制    

#max_connections -1    

 

# cafile:CA證書文件    

# capath:CA證書目錄    

# certfile:PEM證書文件    

# keyfile:PEM密鑰文件    

#cafile    

#capath    

#certfile    

#keyfile    

 

# 必須提供證書以保證數據安全性    

#require_certificate false    

 

# 若require_certificate值爲true,use_identity_as_username也必須爲true    

#use_identity_as_username false    

 

# 啓用PSK(Pre-shared-key)支持    

#psk_hint    

 

# SSL/TSL加密算法,可以使用“openssl ciphers”命令獲取    

# as the output of that command.    

#ciphers    

 

# =================================================================    

# Persistence    

# =================================================================    

 

# 消息自動保存的間隔時間    

#autosave_interval 1800    

 

# 消息自動保存功能的開關    

#autosave_on_changes false    

 

# 持久化功能的開關    

persistencetrue    

 

# 持久化DB文件    

#persistence_file mosquitto.db    

 

# 持久化DB文件目錄    

#persistence_location /var/lib/mosquitto/    

 

# =================================================================    

# Logging    

# =================================================================    

 

# 4種日誌模式:stdout、stderr、syslog、topic    

# none 則表示不記日誌,此配置可以提升些許性能    

log_dest none    

 

# 選擇日誌的級別(可設置多項)    

#log_type error    

#log_type warning    

#log_type notice    

#log_type information    

 

# 是否記錄客戶端連接信息    

#connection_messages true    

 

# 是否記錄日誌時間    

#log_timestamp true    

 

# =================================================================    

# Security    

# =================================================================    

 

# 客戶端ID的前綴限制,可用於保證安全性    

#clientid_prefixes    

 

# 允許匿名用戶    

#allow_anonymous true    

 

# 用戶/密碼文件,默認格式:username:password    

#password_file    

 

# PSK格式密碼文件,默認格式:identity:key    

#psk_file    

 

# pattern write sensor/%u/data    

# ACL權限配置,常用語法如下:    

# 用戶限制:user     

# 話題限制:topic [read|write]     

# 正則限制:pattern write sensor/%u/data    

#acl_file    

 

# =================================================================    

# Bridges    

# =================================================================    

 

# 允許服務之間使用“橋接”模式(可用於分佈式部署)    

#connection     

#address [:]    

#topic  [[[out | in | both] qos-level] local-prefix remote-prefix]    

 

# 設置橋接的客戶端ID    

#clientid    

 

# 橋接斷開時,是否清除遠程服務器中的消息    

#cleansession false    

 

# 是否發佈橋接的狀態信息    

#notifications true    

 

# 設置橋接模式下,消息將會發布到的話題地址    

# $SYS/broker/connection//state    

#notification_topic    

 

# 設置橋接的keepalive數值    

#keepalive_interval 60    

 

# 橋接模式,目前有三種:automatic、lazy、once    

#start_type automatic    

 

# 橋接模式automatic的超時時間    

#restart_timeout 30    

 

# 橋接模式lazy的超時時間    

#idle_timeout 60    

 

# 橋接客戶端的用戶名    

#username    

 

# 橋接客戶端的密碼    

#password    

 

# bridge_cafile:橋接客戶端的CA證書文件    

# bridge_capath:橋接客戶端的CA證書目錄    

# bridge_certfile:橋接客戶端的PEM證書文件    

# bridge_keyfile:橋接客戶端的PEM密鑰文件    

#bridge_cafile    

#bridge_capath    

#bridge_certfile    

#bridge_keyfile    

mosquito 配置用戶名和密碼可以參考https://www.jianshu.com/p/4b545332b495這篇簡書,我這裏做一個簡單demo就不配置用戶名和密碼了。

我們需要改的配置很少

就設置一下host 和port就可以了。配置好後重啓服務就可以生效了。

要注意的地方和Apollo一樣 ,注意端口號是否打開或被佔用。

由於mosquito沒有提供可視化界面,在自己不搭建可視化界面的情況下,我們可以用兩個客戶端訂閱同一主題來測試mosquito服務器。mosquito至此就基本ok了。

四  MQTT客戶端

客戶端一般兩個常用的mqtt三方庫MQTTKit和MQTTClient,MQTTClient在Ios10出來後更新了一版,經常維護;MQTTKit,這個貌似很久沒更新了,所以我們選用MQTTClient,搭建環境爲iOS。

1 安裝MQTTClient

直接用cocopod集成  pod 'MQTTClient'

2相關類

3 具體用法 

這裏做連接的時候 需要先打開你的服務,用mosquito或者Apollo都可以 

用Apollo 是需要加用戶名和密碼的,默認爲admin 和password ,用mosquito則不需要用戶名和密碼。host爲你服務器的ip,port爲你設置的port 我這邊是1883,服務器所在主機和手機在同一局域網內就可以連上,覺得局域網麻煩的大佬可以直接甩到阿里雲之類的服務器上去。連上後,訂閱同一主題的客戶端就能相互通信了,比如在Apollo 服務器下手機客戶端可以和其提供的webdemo通信了。

客戶端接受消息

客戶端發送消息

其他多主題訂閱 或者lastwill遺囑設置或者retain設置參考MQTTClient的註釋。

最後 用完後記得釋放資源

至此,一個簡單的MQTT協議從服務端到客戶端的實現到此就完成了,歡迎大家補充完善。



作者:子夏的不語
鏈接:https://www.jianshu.com/p/3d5b487c6860
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯繫作者獲得授權並註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章