初始 MQTT
物聯(lián)網(wǎng) (internet of thing) ,表示的是可以把一些帶某些傳感器的設(shè)備(終端),接入到互聯(lián)網(wǎng)的行為策菜。
通過互聯(lián)網(wǎng)連接這些設(shè)備厚掷,這些設(shè)備就能夠互相協(xié)作。
而MQTT就是這些設(shè)備之間數(shù)據(jù)通信的一個(gè)基于 TCP/IP 的協(xié)議。
每個(gè)終端都和實(shí)現(xiàn)了 MQTT 協(xié)議的代理/服務(wù)器相連。
通過 published MQTT 代理服務(wù)器的某個(gè)主題 發(fā)送數(shù)據(jù)。
通過 subscription 從 MQTT 代理服務(wù)器獲取自己訂閱的 主題 數(shù)據(jù)栓始。
代理服務(wù)器本身不產(chǎn)生數(shù)據(jù),數(shù)據(jù)全是由鏈接到這個(gè)代理服務(wù)器的終端產(chǎn)生血当。
終端往服務(wù)器發(fā)送數(shù)據(jù)幻赚,在服務(wù)器訂閱了主題的終端禀忆,接受另外一個(gè)終端發(fā)送到服務(wù)器,并通過服務(wù)器轉(zhuǎn)發(fā)到自己落恼。
為何選擇 MQTT 協(xié)議箩退?
MQTT 協(xié)議是一種輕量級(jí)的、靈活的網(wǎng)絡(luò)協(xié)議佳谦。并且非常適合 IOT 的場(chǎng)景戴涝。
- 首先 IOT 協(xié)議的定義非常小巧,不會(huì)像 HTTP钻蔑、HTTPS 那么重量級(jí)啥刻。
- 一般支持 IOT 的設(shè)備的網(wǎng)絡(luò)傳輸環(huán)境和自身的計(jì)算能力都比價(jià)薄弱。正好合適MQTT 對(duì)網(wǎng)絡(luò)和數(shù)據(jù)要求不高的輕量級(jí)協(xié)議咪笑。
為什么不選擇其他的網(wǎng)絡(luò)協(xié)議可帽?
大多數(shù)開發(fā)人員已經(jīng)熟悉了 HTTP WEB 協(xié)議。那么為什么不讓 IOT 設(shè)置鏈接到 WEB 服務(wù)窗怒?
設(shè)備可以采用 HTTP 請(qǐng)求的形式發(fā)送數(shù)據(jù)映跟,并采用 HTTP 響應(yīng)的形式從服務(wù)器獲取數(shù)據(jù),接受更新扬虚。
因?yàn)閷?duì)于 IOT 的設(shè)備來說努隙,這種主動(dòng)請(qǐng)求--> 被動(dòng)等待應(yīng)答的 數(shù)據(jù)傳輸模型存在嚴(yán)重的局限性:
HTTP 是一種同步協(xié)議」缄牵客戶端需要等待服務(wù)器的響應(yīng)荸镊。Web 瀏覽器具有這樣的要求,但它的代價(jià)是犧牲了可伸縮性路鹰。 在 IoT 領(lǐng)域,大量的設(shè)備以及很可能不可靠或者高延遲的網(wǎng)絡(luò)使得同步通信成為問題收厨。異步消息協(xié)議更適合 IoT 應(yīng)用程序晋柱。傳感器只負(fù)責(zé)發(fā)送數(shù)據(jù),讓網(wǎng)絡(luò)確定將其傳送到目標(biāo)設(shè)備和服務(wù)器的最佳路線和時(shí)間诵叁。
HTTP 是單向的雁竞。客戶端必須主動(dòng)的發(fā)起請(qǐng)求拧额。在 IoT 應(yīng)用程序中碑诉,設(shè)備或傳感器通常是客戶端,就意味著侥锦,除非用戶或應(yīng)用程序主動(dòng)請(qǐng)求进栽,否則無法接受來自服務(wù)器的數(shù)據(jù)。
HTTP 是一個(gè) 1-1 的協(xié)議恭垦】烀客戶端發(fā)出請(qǐng)求格嗅,服務(wù)器進(jìn)行相應(yīng)。它們是一對(duì)一的對(duì)應(yīng)關(guān)系唠帝。但是需要把 HTTP 這種 1-1的關(guān)系屯掖,改進(jìn)程 IOT 中很常見的 1 對(duì)多的關(guān)系,實(shí)現(xiàn)起來很困難襟衰,而且成本也很高贴铜。而 1 對(duì)多在 IoT 中很常見。
HTTP 相對(duì)于 MQTT 來說瀑晒,是一個(gè)比較重的協(xié)議绍坝,它不適合IOT 終端設(shè)備受限的網(wǎng)絡(luò)和較差的計(jì)算能力。
那么瑰妄,MQTT 為什么如此輕便且靈活陷嘴?MQTT 協(xié)議的一個(gè)關(guān)鍵的特性是 發(fā)布/訂閱模型。它將數(shù)據(jù)的發(fā)布者和接受者分離间坐。
一個(gè)設(shè)備終端既可以是數(shù)據(jù)的發(fā)布者(published) 也可以是數(shù)據(jù)的訂閱者(subscription)灾挨。
一個(gè)設(shè)備如果要發(fā)布數(shù)據(jù),只需要往代理服務(wù)器中相應(yīng)的主題發(fā)布數(shù)據(jù)內(nèi)容即可竹宋。
一個(gè)設(shè)備如果需要接受到數(shù)據(jù)劳澄,只需要在代理服務(wù)器中,提前訂閱自己需要關(guān)注的主題即可蜈七。
MQTT 的基本體驗(yàn)
MQTT 最基本的體驗(yàn)秒拔,就是使用 mosquitto
。
Mosquitto是一款實(shí)現(xiàn)了 MQTT v3.1 協(xié)議的開源消息代理軟件飒硅,提供輕量級(jí)的砂缩,支持發(fā)布/訂閱的的消息推送模式,使設(shè)備對(duì)設(shè)備之間的短消息通信簡(jiǎn)單易用三娩。
它可以理解成一個(gè) MQTT 的代理服務(wù)器庵芭。
基本步驟如下:
- 首先使用
brew install
brew install mosquitto
安裝成功截圖
使用 brew services start mosquitto
啟動(dòng) MQTT 服務(wù)
運(yùn)行截圖
然后再打開另外兩個(gè)終端窗口,模擬兩個(gè)IOT設(shè)備雀监。A 訂閱 MQTT 服務(wù)双吆。B 向 MQTT 的服務(wù)發(fā)送數(shù)據(jù)。
A訂閱當(dāng)前MQTT的某個(gè)服務(wù)会前。
mosquitto_sub -t "dw/demo"
B向 MQTT 服務(wù)器發(fā)布(published) 數(shù)據(jù)。
mosquitto_pub -t "dw/demo" -m "hello MQTT"
然后瓦宜,我們就可以在A控制臺(tái)里看到由 B 通過 MQTT 服務(wù)發(fā)送的數(shù)據(jù)了临庇。
基本流程圖
控制臺(tái) A 向 MQTT 服務(wù)器訂閱 dw/demo 服務(wù)笛坦,并被動(dòng)的等待 MQTT 服務(wù)器返回?cái)?shù)據(jù)区转。
控制臺(tái) B 主動(dòng)的向 MQTT 服務(wù)器的 dw/demo 服務(wù)發(fā)送 published 數(shù)據(jù),之后版扩。服務(wù)器會(huì)主動(dòng)向事先訂閱了 dw/demo 的終端分發(fā)此消息废离。
了解 MQTT 協(xié)議
MQTT 是一種鏈接協(xié)議,它指定了如何組織數(shù)據(jù)字節(jié)并通過 TCP/IP 網(wǎng)絡(luò)傳輸它們礁芦。但實(shí)際上蜻韭,開發(fā)人員并不需要鏈接這個(gè)鏈接協(xié)議的具體細(xì)節(jié)。我們只需要知道柿扣,每條消息都有一個(gè)命令和數(shù)據(jù)有效負(fù)載肖方。該命令定義消息類型(比如 CONNECT 消息或者 SUB SCRIBE 消息)。所有的 MQTT 庫(kù)和工具都提供了直接處理這些消息的基本方法未状,并且能自動(dòng)填充一些必要的字段(在數(shù)據(jù)包的對(duì)應(yīng)字節(jié)填充)俯画,比如消息和客戶端 ID。
首先客戶端發(fā)送一條CONNECT消息來鏈接代理司草。CONNECT 消息要求建立從客戶端到代理服務(wù)器的鏈接艰垂。
CONNECT 命令的基本參數(shù)
-
cleanSession
: 此標(biāo)志指定是否是持久鏈接。持久會(huì)話會(huì)將所有的訂閱和可能丟失的消息(具體取決于 QoS)都存儲(chǔ)在代理(服務(wù)器)中埋虹。 -
username
: 鏈接代理服務(wù)器的用戶名猜憎。(對(duì),代理服務(wù)器不是誰想連搔课,想連就能連) -
password
: 鏈接代理服務(wù)器的密碼胰柑。(對(duì),代理服務(wù)器不是誰想連爬泥,想連就能連) -
lasWillTopic
: 鏈接意外中斷柬讨,代理服務(wù)器會(huì)像某個(gè)主題發(fā)送一條last will
消息。 -
lastWillQos
:last will
消息的 QoS袍啡。 -
lastWillMessage
:last will
消息本身踩官。 -
KeepAlive
: 這是客戶端通過 ping 服務(wù)器來保持鏈接有效所需的時(shí)間間隔。
當(dāng)客戶端向代理服務(wù)器發(fā)送一條 CONNECT 命令之后葬馋,服務(wù)器會(huì)調(diào)用 CONNACK命令卖鲤,告知服務(wù)鏈接的狀態(tài)肾扰。
CONNACK 命令的基本參數(shù)
-
sessionPresent
: 此參數(shù)表明鏈接是否已有一個(gè)持久會(huì)話畴嘶。也就是說,連接了訂閱的主題集晚,而且會(huì)接受丟失的消息窗悯??偷拔? -
returnCode
: 0 表示成功蒋院。otherwise 失敗亏钩。
當(dāng)客戶端和服務(wù)器建立連接之后,客戶端就可以向服務(wù)器訂閱某些主題的欺旧。(發(fā)送一條或多條 SUBSCRIBE消息)姑丑。
表明當(dāng)服務(wù)器接受到其他終端推送的此主題數(shù)據(jù)時(shí),服務(wù)器會(huì)默認(rèn)發(fā)送給它辞友。
SUBSCRIBE 參數(shù)列表
-
QoS
: 服務(wù)質(zhì)量 (quality of services)栅哀。一般有3個(gè)枚舉值。- 0 : 表示不可靠服務(wù)称龙,消息僅推送一次留拾,如果當(dāng)前客戶端在線,或者因?yàn)榫W(wǎng)絡(luò)原因鲫尊,沒有收到就沒有收到痴柔。
- 1 : 消息至少傳遞 1 次。一次不成功疫向,傳遞第二次咳蔚,第 N 次『枧酰可能會(huì)出現(xiàn)重復(fù)數(shù)據(jù)的情況屹篓。
- 2 : 消息恰好傳遞 1 次。雙方通過 4 次握手匙奴,保證消息能準(zhǔn)確的從服務(wù)器傳遞給客戶端堆巧,而且只傳一次。
d
QoS 參數(shù)雖然在客戶端指定泼菌,但規(guī)定的是服務(wù)器傳遞數(shù)據(jù)的模式谍肤。所以,QOS 是用來約束服務(wù)器哗伯,而不是客戶端本身荒揣。
-
topic
: 客戶端要訂閱的主題。
一個(gè)主題可以有多個(gè)級(jí)別焊刹,級(jí)別之間用斜杠字符分隔系任。例如 ,
"dw/demo"
和"/ibm/bluemix/qmqt"
都是有效主題。
當(dāng)客戶端成功的向服務(wù)器訂閱某個(gè)主題之后虐块,服務(wù)器會(huì)返回一條 SUBACK 的消息俩滥,其中包含一個(gè)或者多個(gè) returnCode 參數(shù)。
SUBACK消息參數(shù)
returnCode
: 值 0 - 2 贺奠,表示成功訂閱霜旧,并返回這個(gè)訂閱消息的 QOS。值 128 : 訂閱失敗儡率。
既然客戶端可以向服務(wù)器訂閱某個(gè)主題挂据,當(dāng)然也可以取消訂閱以清。
與SUBSCRIBE訂閱命令相反的命令是UNSUBSCRIBE取消訂閱命令。
此命令非常簡(jiǎn)單崎逃。只有一個(gè)topic(主題)參數(shù)掷倔。
-
topic
: 此參數(shù)就是客戶端取消訂閱的主題。
上面講的是訂閱个绍,訂閱是需要有消息從服務(wù)器發(fā)送過來的今魔。但是服務(wù)器本身基本不產(chǎn)生數(shù)據(jù),那數(shù)據(jù)從何而來呢障贸?
通過另外一個(gè)客戶端執(zhí)行PUBLISH命令错森,往代理服務(wù)器發(fā)送數(shù)據(jù)。并最終通過代理服務(wù)器將數(shù)據(jù)傳遞給訂閱了此服務(wù)的客戶端篮洁。
PUBLISH 消息參數(shù)
-
topicName
: 發(fā)布消息的相關(guān)主題涩维。 -
qos
: 消息傳遞的質(zhì)量水平。(約束服務(wù)器) -
retainFlag
: 此標(biāo)志表明服務(wù)器是否保留該消息作為針對(duì)此主題的最后一條已知消息袁波。 -
payload
: 消息中的實(shí)際數(shù)據(jù)瓦阐。它可以是文本字符串或者二進(jìn)制大對(duì)象數(shù)據(jù)(圖片)
對(duì)于 MQTT 的一張基本理解圖
基本流程圖:
最后總結(jié)
- MQTT 是一個(gè)輕量級(jí),用于計(jì)算能力弱篷牌,網(wǎng)絡(luò)環(huán)境差的終端設(shè)備之間的數(shù)據(jù)傳輸睡蟋。
- MQQ 是基于一個(gè) 發(fā)布/訂閱 的基本模式。
- 每個(gè)終端都可以從服務(wù)器訂閱某些主題枷颊,也可以往代理服務(wù)器發(fā)布某些主題戳杀。
- 當(dāng)服務(wù)器接受到了某些終端發(fā)送過來的數(shù)據(jù)之后,會(huì)向訂閱了這個(gè)服務(wù)的終端推送這些數(shù)據(jù)夭苗。
參考資料:初識(shí) MQTT