從零開始實現(xiàn)一個MQTT客戶端---開篇漫談

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)這個庫。大致的流程是:

  1. socket通訊的建立
  2. Connect Command的發(fā)送
  3. 解析接收的消息姜挺,依據(jù)首字節(jié)高四位命令區(qū)分消息類型齿税。
  4. PINGREQ/PINGRESP的處理(連接的keep alive)
  5. SUBSCRIBE/UNSUBSCRIBE的處理 (消息的訂閱與取消訂閱)
  6. PUBLISH的實現(xiàn)
  7. 異步的支持
  8. TLS/SSL的支持
  9. 細(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ù)提供安全保障律姨。

tls/ssl

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)容
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末郎哭,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子菇存,更是在濱河造成了極大的恐慌夸研,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撰筷,死亡現(xiàn)場離奇詭異陈惰,居然都是意外死亡,警方通過查閱死者的電腦和手機毕籽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來井辆,“玉大人关筒,你說我怎么就攤上這事”保” “怎么了蒸播?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長萍肆。 經(jīng)常有香客問我袍榆,道長,這世上最難降的妖魔是什么塘揣? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任包雀,我火速辦了婚禮,結(jié)果婚禮上亲铡,老公的妹妹穿的比我還像新娘才写。我一直安慰自己葡兑,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布赞草。 她就那樣靜靜地躺著讹堤,像睡著了一般。 火紅的嫁衣襯著肌膚如雪厨疙。 梳的紋絲不亂的頭發(fā)上洲守,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音沾凄,去河邊找鬼梗醇。 笑死,一個胖子當(dāng)著我的面吹牛搭独,可吹牛的內(nèi)容都是我干的婴削。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼牙肝,長吁一口氣:“原來是場噩夢啊……” “哼唉俗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起配椭,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤虫溜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后股缸,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體衡楞,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年敦姻,在試婚紗的時候發(fā)現(xiàn)自己被綠了瘾境。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡镰惦,死狀恐怖迷守,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情旺入,我是刑警寧澤兑凿,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站茵瘾,受9級特大地震影響礼华,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拗秘,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一圣絮、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧聘殖,春花似錦晨雳、人聲如沸行瑞。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽血久。三九已至,卻和暖如春帮非,著一層夾襖步出監(jiān)牢的瞬間氧吐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工末盔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留筑舅,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓陨舱,卻偏偏與公主長得像翠拣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子游盲,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容