iOS MQTT----MQTTClient實戰-看這篇的就夠了

很久沒有寫東西了,半年搞1個半app,2個ipad項目,人已瘋。。。。

今天在重構代碼,總結一下:MQTT的使用和坑

MQTT 是IBM開發的一個即時通訊協議,有可能成為物聯網的重要組成部分。該協議支持所有平臺,幾乎可以把所有聯網物品和外部連接起來,被用來當做傳感器和致動器(比如通過Twitter讓房屋聯網)的通信協議 ----------------------百度詞條解釋


應用場景

MQTT是一個設計得非常出色的傳輸層協議,在移動消息、物聯網、車聯網、智能硬件甚至能源勘探等領域有著廣泛的應用。1個字節報頭、2個字節心跳、消息QoS支持等設計,非常適合在低帶寬、不可靠網絡、嵌入式設備上應用。

不同的應用有不同的系統要求,用戶使用emqttd消息服務器前,可以按自己的應用場景進行測試,而不是簡單的連接壓力測試:

Android消息推送: 推送消息廣播測試。

移動即時消息應用: 消息收發確認測試。

智能硬件應用: 消息的往返時延測試。

物聯網數據采集: 并發連接與吞吐測試


其他的不多說,有很多資料,一般常用的有兩個MQTT

1.MQTTKit

2.MQTTClient

兩個都用過,不過目前用的是MQTTClient,在Ios10出來后更新了一版,經常維護;

MQTTKit,這個貌似很久沒更新了,也不多說


首先明確一下你拿這個東西干嘛的,拿我做的app來說:

在地圖頁面,請求歷史數據,然后通過mqtt訂閱主題,獲取終端的返回的數據,然后實時更新數據,效果就類似于打車軟件的樣子,實現實時監控數據等功能。


第一步:安裝MQTT

MQTT-Client-Framework ? GitHub地址

用cocopod的直接,下載就好 ? pod 'MQTTClient'


第二步:



安裝好之后就這樣,每個類一看知道就是干嘛,直接上代碼詳細說


第三步:

導入 #import<MQTTClient/MQTTClient>

1.設置地址和端口號.

2.設置mqtt的賬號和密碼,同樣找好基友要

3. 最后訂閱主題,這個地方看了很多人寫的博客,假設你的主題很多比如5個,10個,使用線程處理,這樣也是可以的,但是不是最優化的方式,后面會詳細說明,對了mqtt是可以同時訂閱多個主題的,很多資料都未說明.

這個地方用了枚舉,主要是為了判斷訂閱主題,來處理回調的數據

//注意:訂閱主題不能放到子線程進行,否則block不會回調

//下面這些都是自己封裝過得

//主題格式 ? ? ? ? ?@“$IOT/haha/datapoint/motor_control”

//如果不封裝就是這樣的

這樣就實現了主題訂閱,訂閱成功后會有log,一堆信息,這樣的

第四步:實現Session代理方法,處理數據

在代理方法中,就可以得到對應的數據,在這里說明一下

1.如果你訂閱的主題只有一個,那么你不判斷也是可以的,但是如果有多個主題,你需要判斷,返回的哪個對應的主題,然后才能處理數據。

2.你訂閱主題假如是這樣的 ? ?@“$IOT/haha/datapoint/motor_control” ?,那么在處理數據時,你判斷“motor_control”字符串就可以找到對應的數據,判斷最后的參數就行,看截圖就明白了.

3.然后拿到你的數據,你想干嘛就干嘛.


(⊙o⊙)…,到這里基本的就完了,那是不可能的,我發現很多資料寫到這里就完了,還有很多的重點沒說明,不然整理東西就沒意義了.



可能大家用處不一樣的,有人會碰到,有人不會,在這里說明一下,可能會遇到的問題:


1.先說常用的屬性,如果你一直把mqtt開著,你不處理,那么mqtt一直會有數據返回,我這邊就是1秒一次,然后一堆數據....

在剛開始的時候,初始化了 MQTTSession 的對象,看截圖

[self.mySession disconnect] 斷開連接 對應的就是 [self.mySession connect] 重新連接

如果不需要mqtt了,記得close,不然mqtt還會返回數據.

當然這個截圖,只是全部舉例說明,如果不用mqtt直接,close就搞定,不需要寫這么多.

2.在正常情況下,你的mqtt成功訂閱了主題,那么它會一直在監聽服務器是否有數據返回,但是有的時候嘛,你會遇到下面這中情況,mqtt停止了,當然排除你自己 close的情況外.

這種情況就很坑爹啦,你用mqtt的目的是啥,就是要實時監控嘛。。。。

在我查詢的資料中有幾種解釋:

前提是你家的服務器一直在發送數據,而不是停掉了

2.1 你的clientID,沒有設置,簡單說明,你有一個賬號是老王,那么你登錄了,你的同事也登錄了,這個時候,mqtt會自動掉線。

self.mySession.clientId 有這個屬性,我咨詢過后臺,說移動端要設置,設置成功就可以避免,但是如果你用的是,MQTTClient 這個,完全不用,因為別人已經處理好了,可以自己點擊進去看看,那么如果你用的是其他的第三方,clientId需要取隨機數,不能相同.

2.2 碰到上面這個問題咋辦呢,MQTTClient 沒有斷線重連的機制,也可能是我沒找到,哪位小伙伴看到了也麻煩告訴我一聲.

這個時候,你需要監聽消息的狀態,就可以處理了,來看看,self.mySession.status的值

在上面也寫到了,如果你使用disconnect\connect,那么消息的狀態最終都會輸出第五個MQTTSessionStatusClosed.

2.3 介紹兩種監聽方法:

2.3.1 ?KVO ? ?在創建MQTTSession對象的時候,添加就可以了

這樣只要消息關閉了,那么mqtt會立即重連;但是會有一個問題,如果你的mqtt只是部分頁面用,離開這個頁面之后,mqtt還會繼續監聽,不停的創建對象,上面解釋過了,消息狀態最終都是MQTTSessionStatusClosed.

2.3.2 目前我在用就是定時器,用定時器處理消息狀態


好處就是,離開頁面的時候,mqtt關閉,定時器也關閉,不會導致kvo那種情況出現,壞處暫時沒發現.

這樣就可以讓mqtt一只處于監控的狀態下了.


3.關于MQTT一次性訂閱多個主題,每個mqtt框架都可以。

假如你要一次性訂閱10個主題,那么你不得寫十次么,完全不用這樣,現在介紹一個更簡單的辦法,

你只需要更改一個地方就可以了,主題URL

上面我寫的主題格式是這樣的

//主題格式 ? ? ? ? ?@“$IOT/haha/datapoint/motor_control”

現在你只需要把主題的URL ?改成這樣 ?@"$IOT/haha/#"

MQTT主題(Topic)支持’+’, ‘#’的通配符,’+’通配一個層級,’#’通配多個層級(必須在末尾)

解釋一下,#表示,haha下面的所有主題,假如你有10個主題,你這樣就可以一次性訂閱完成,然后你在返回的數據中,判斷對應的主題處理數據就可以了.

代碼中就可以把其它的注釋掉.

話又說回來,一個頁面你只用到一個主題的內容,你難道也這樣寫嘛,所以一切看實際情況。


4.最后說一個,MQTT超時時間設置的問題.

[self.mySession connectAndWaitTimeout:1];

MQTT在網絡情況不太好/接收不到服務器數據時,容易導致線程卡住,你懂得,什么都不能點了,建議把這里的時間設置小一點.


5.其他

最最后,補充一個網站,后臺搭建mqtt服務器,移動端使用原理介紹都可以用,MQTT介紹的很全面了,深入了解的可以看看,有swift和oc的版本,這個我沒用過,原理一樣.

MQTT-EMQ服務器搭建


6.DEMO 下載地址 ? ?暫無,弄好了再傳

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容