iOS開發(fā)中鉴竭,關(guān)于MQTT的三方庫主要有兩種歧譬。
- 基于C實現(xiàn)的Mosquitto庫岸浑。當(dāng)然直接去調(diào)用C的接口并不是特別的舒服,所以用一個ObjC的類作為橋接瑰步。比如MQTTKit矢洲。
- 使用ObjC或者Swift的原生實現(xiàn)。包括ObjC實現(xiàn)的MQTT-Client 缩焦,Swift實現(xiàn)的 CocoaMQTT读虏。
最近花時間分析了一下Mosquitto庫的源碼。我嘗試按照MQTT協(xié)議的流程來依次拆分mosquitto庫并逐步的模仿實現(xiàn)出一個客戶端可用的網(wǎng)絡(luò)庫(有關(guān)Broker的實現(xiàn)還需要處理訂閱/取消訂閱和一些額外的操作處理袁滥,暫時先不考慮這些)盖桥。具體的代碼我放在了Github MQTTService上,之后的文章我會分篇依次描述過程题翻。
這里是MQTT文檔-中文版揩徊。要實現(xiàn)一個可靠的MQTT網(wǎng)絡(luò)庫,實際上我們需要做的就是將文檔第三章中各種控制報文的邏輯用編程語言實現(xiàn)出來嵌赠。在后續(xù)的文章里塑荒,我會參考各種控制報文的簡易程度而不是文檔介紹的報文順序來實現(xiàn)這個庫。大致的流程是:
- socket通訊的建立
- Connect Command的發(fā)送
- 解析接收的消息姜挺,依據(jù)首字節(jié)高四位命令區(qū)分消息類型齿税。
- PINGREQ/PINGRESP的處理(連接的keep alive)
- SUBSCRIBE/UNSUBSCRIBE的處理 (消息的訂閱與取消訂閱)
- PUBLISH的實現(xiàn)
- 異步的支持
- TLS/SSL的支持
- 細(xì)節(jié)的完善
PUBLISH涉及不同Qos的處理。而且與上面的消息類型有所不同的是炊豪,PUBLISH是Broker和Client互推凌箕,需要針對每一種send以及ack都做出對應(yīng)的處理。這一部分細(xì)分為以下幾塊
不同Qos的PUBLISH的發(fā)送
- Qos = 0:發(fā)送成功即可
- Qos = 1:需要接收到PUBACK
- Qos = 2:需要處理PUBREC/PUBREL/PUBCOMP三種情況
MQTT是一個基于TCP/IP協(xié)議簇實現(xiàn)的應(yīng)用層協(xié)議(UDP版本的是MQTT-SN)词渤,在Mosquitto
中底層的通訊是基于socket
實現(xiàn)的牵舱。當(dāng)然,你也可以使用Websocket
掖肋。這里我不做贅述仆葡,雖然兩者名字類似但就像Java和Javascript一樣實際這是兩個完全不同的概念。有關(guān)socket
的內(nèi)容可以參考我翻譯的Python官網(wǎng)的一份文檔How to socket。
MQTT協(xié)議本身是明文傳輸?shù)难刂选V詴P(guān)心到這個問題是因為之前項目在公司測試沒有問題把篓,但是在HK的公共wifi環(huán)境下一直出現(xiàn)用戶名和密碼錯誤的問題。雖然最后問題解決不是因為數(shù)據(jù)報被篡改腰涧,但MQTT作為應(yīng)用層協(xié)議韧掩,MQTT僅關(guān)注消息傳輸,提供合適的安全功能是我們實現(xiàn)者的責(zé)任窖铡。使用TLS [RFC5246] 是比較普遍的選擇疗锐。這里多說一點,有計算機網(wǎng)絡(luò)基礎(chǔ)的讀者應(yīng)該知道费彼,TCP/IP協(xié)議五層模型
滑臊。當(dāng)然,也有七層的說法箍铲,多出的兩層是將會話層
雇卷、表示層
從應(yīng)用層
中獨立出來,讓多個應(yīng)用程序能夠共享著兩層的代碼颠猴。但是因為各個應(yīng)用程序之間會話和表達(dá)的需求差異很大关划,所以這兩個網(wǎng)絡(luò)層算是只存在我們的書本里實際中并沒有實現(xiàn)。但是無心插柳柳成蔭翘瓮,一個提供安全加密服務(wù)層出現(xiàn)了贮折,它為我們應(yīng)用層的協(xié)議提供了安全服務(wù)。這就是TLS/SSL
资盅,但是并沒有在實際的模型中單獨為它劃出一層來调榄。我們熟知的HTPPS
就是有了安全保護(hù)的HTTP
協(xié)議。類似HTTP/SMTP/FTP
包括我們今天所說的MQTT
這些應(yīng)用層的協(xié)議都可以使用TLS/SSL
來為我們的網(wǎng)絡(luò)服務(wù)提供安全保障律姨。
在MQTT
協(xié)議中有一個非常重要的概念Qos
振峻。如果Qos
為0,就是普通的消息發(fā)送择份,成功與否完全依靠底層也就是TCP/IP協(xié)議簇
扣孟;Qos
為1確保消息至少送達(dá)一次這個就是消息的送達(dá)確認(rèn)和TCP的ack類似;Qos
為2確保消息只送到一次也就是TCP
的保證唯一性荣赶。MQTT
作為上層協(xié)議部分機制是和TCP
重復(fù)的凤价。原因很簡單,ack的確認(rèn)只是確認(rèn)了數(shù)據(jù)包進(jìn)入了tcp棧拔创,但上層應(yīng)用是否接收處理并不能保證利诺,所以我們需要在應(yīng)用層做一個應(yīng)答。但既然MQTT
協(xié)議實現(xiàn)了數(shù)據(jù)報確認(rèn)和重傳這部分的邏輯剩燥,底層協(xié)議的選擇上TCP
協(xié)議相對UDP
協(xié)議還會有什么較大的優(yōu)勢嗎(流量控制以及有序的傳輸)慢逾,甚至在弱網(wǎng)絡(luò)環(huán)境下TCP
連接的建立以及消息的確認(rèn)都會成為網(wǎng)絡(luò)沉重的負(fù)擔(dān)立倍。
做一個簡單的討論:如果網(wǎng)絡(luò)狀況一切良好,那么所有數(shù)據(jù)包確認(rèn)的操作在TCP都已經(jīng)得到了保證侣滩,每一條消息都只成功發(fā)送一次口注,那么應(yīng)用層MQTT協(xié)議的確認(rèn)是否還有必要。如果是弱網(wǎng)絡(luò)環(huán)境下君珠,TCP連接不停的中斷和重連寝志,那么就會給本身壓力就很大網(wǎng)絡(luò)增添更多的麻煩。TCP在網(wǎng)絡(luò)層實現(xiàn)了消息的超時重傳策添,應(yīng)用層的MQTT也會有重傳的機制材部,會不會造成一條消息重復(fù)發(fā)送多次的情況。
實現(xiàn)一個能夠通訊的網(wǎng)絡(luò)庫邏輯并不復(fù)雜唯竹,主要的問題在于需要你對照文檔去挨個解析傳輸?shù)臄?shù)據(jù)的含義乐导。作為一名應(yīng)用層的開發(fā)人員,日常情況下我們使用HTTP等通訊協(xié)議摩窃,拿到的是json
或者XML
格式的數(shù)據(jù)兽叮,這是非常容易閱讀和解析的數(shù)據(jù)。但在實現(xiàn)網(wǎng)絡(luò)庫的過程中猾愿,對于報文的信息你需要精確到每一個字節(jié)的每一個bit。簡單的1和0我們按照協(xié)議賦予了他們各種不同的含義账阻。如何從這一串?dāng)?shù)據(jù)中讀取到我們想要的內(nèi)容蒂秘,非常的考驗細(xì)心和耐心。
如果你對MQTT協(xié)議是什么淘太,用來做什么姻僧,優(yōu)缺點是什么還有疑問,可以參考官方文檔 - 中文版蒲牧。我在這里也為大家做一個網(wǎng)上知識的總結(jié)撇贺。具體的細(xì)節(jié)你可以先放開不去關(guān)心,在后面的文章里我們會一一的用代碼去實現(xiàn)冰抢。
有興趣的朋友可以關(guān)注一下松嘶,之后的文章會分篇詳細(xì)解答 :)
一· 什么是MQTT
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發(fā)的一個即時通訊協(xié)議挎扰,該協(xié)議支持所有平臺翠订,也就是說不論什么平臺都可以使用集成此協(xié)議,網(wǎng)上大多說該協(xié)議用于物聯(lián)網(wǎng)遵倦,尽超,有可能成為物聯(lián)網(wǎng)的重要組成部分。幾乎可以把所有聯(lián)網(wǎng)物品和外部連接起來梧躺,被用來當(dāng)做傳感器和致動器(比如通過Twitter讓房屋聯(lián)網(wǎng))的通信協(xié)議似谁。
** 二· MQTT有什么特點**
MQTT協(xié)議是為大量計算能力有限,且工作在低帶寬、不可靠的網(wǎng)絡(luò)的遠(yuǎn)程傳感器和控制設(shè)備通訊而設(shè)計的協(xié)議巩踏,它具有以下主要的幾項特性:
1斜筐、使用發(fā)布/訂閱消息模式,提供一對多的消息發(fā)布蛀缝,解除應(yīng)用程序耦合顷链;
2、對負(fù)載內(nèi)容屏蔽的消息傳輸屈梁;
3嗤练、使用 TCP/IP 提供網(wǎng)絡(luò)連接;
4在讶、有三種消息發(fā)布服務(wù)質(zhì)量:
至多一次
煞抬,消息發(fā)布完全依賴底層 TCP/IP 網(wǎng)絡(luò)。會發(fā)生消息丟失或重復(fù)构哺。這一級別可用于如下情況革答,環(huán)境傳感器數(shù)據(jù),丟失一次讀記錄無所謂曙强,因為不久后還會有第二次發(fā)送残拐。
至少一次
,確保消息到達(dá)碟嘴,但消息重復(fù)可能會發(fā)生溪食。
只有一次
,確保消息到達(dá)一次娜扇。這一級別可用于如下情況错沃,在計費系統(tǒng)中,消息重復(fù)或丟失會導(dǎo)致不正確的結(jié)果雀瓢。
5枢析、小型傳輸,開銷很腥恤铩(固定長度的頭部是 2 字節(jié))醒叁,協(xié)議交換最小化,以降低網(wǎng)絡(luò)流量嫌蚤;
** 三· MQTT實現(xiàn)方式 **
** 四· MQTT中常見的概念**
-
MQTT客戶端
一個使用MQTT協(xié)議的應(yīng)用程序或者設(shè)備辐益,它總是建立到服務(wù)器的網(wǎng)絡(luò)連接⊥阎ǎ客戶端可以:
發(fā)布其他客戶端可能會訂閱的信息
- 訂閱其它客戶端發(fā)布的消息
- 退訂或刪除應(yīng)用程序的消息
- 斷開與服務(wù)器連接
-
MQTT服務(wù)器
MQTT服務(wù)器以稱為“消息代理”(Broker)智政,可以是一個應(yīng)用程序或一臺設(shè)備。它是位于消息發(fā)布者
和訂閱者之間箱蝠,它可以:
- 接受來自客戶的網(wǎng)絡(luò)連接
- 接受客戶發(fā)布的應(yīng)用信息
- 處理來自客戶端的訂閱和退訂請求
- 向訂閱的客戶轉(zhuǎn)發(fā)應(yīng)用程序消息
- MQTT協(xié)議中的訂閱续捂、主題垦垂、會話
- 訂閱(Subscription)
訂閱包含主題篩選器(Topic Filter)和最大服務(wù)質(zhì)量(QoS)。訂閱會與一個會話(Session)關(guān)聯(lián)牙瓢。一個會話可以包含多個訂閱劫拗。每一個會話中的每個訂閱都有一個不同的主題篩選器。 - 會話(Session)
每個客戶端與服務(wù)器建立連接后就是一個會話矾克,客戶端和服務(wù)器之間有狀態(tài)交互页慷。會話存在于一個網(wǎng)絡(luò)之間,也可能在客戶端和服務(wù)器之間跨越多個連續(xù)的網(wǎng)絡(luò)連接胁附。 - 主題名(Topic Name)
連接到一個應(yīng)用程序消息的標(biāo)簽酒繁,該標(biāo)簽與服務(wù)器的訂閱相匹配。服務(wù)器會將消息發(fā)送給訂閱所匹配標(biāo)簽的每個客戶端控妻。 - 主題篩選器(Topic Filter)
一個對主題名通配符篩選器州袒,在訂閱表達(dá)式中使用,表示訂閱所匹配到的多個主題弓候。 - 負(fù)載(Payload)
消息訂閱者所具體接收的內(nèi)容