ios MQTT協議及通訊的解決方案
MQTT關系圖
做消息推送有一段時間了,想和大家分享一下通過MQTT消息推送的解決方案。
一、MQTT簡介
MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸)是IBM開發的一個即時通訊協議,該協議支持所有平臺,也就是說不論什么平臺都可以使用集成此協議,網上大多說該協議用于物聯網,,有可能成為物聯網的重要組成部分。幾乎可以把所有聯網物品和外部連接起來,被用來當做傳感器和致動器(比如通過推ter讓房屋聯網)的通信協議。
二、MQTT特點
MQTT協議是為大量計算能力有限,且工作在低帶寬、不可靠的網絡的遠程傳感器和控制設備通訊而設計的協議,它具有以下主要的幾項特性:
1、使用發布/訂閱消息模式,提供一對多的消息發布,解除應用程序耦合;
2、對負載內容屏蔽的消息傳輸;
3、使用 TCP/IP 提供網絡連接;
4、有三種消息發布服務質量:
“至多一次”,消息發布完全依賴底層 TCP/IP 網絡。會發生消息丟失或重復。這一級別可用于如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因為不久后還會有第二次發送。
“至少一次”,確保消息到達,但消息重復可能會發生。
“只有一次”,確保消息到達一次。這一級別可用于如下情況,在計費系統中,消息重復或丟失會導致不正確的結果。
5、小型傳輸,開銷很小(固定長度的頭部是 2 字節),協議交換最小化,以降低網絡流量;
三、ios端 MQTT集成解決方案
我使用過兩個github上的三方庫
1.MQTTKit
https://github.com/mobile-web-messaging/MQTTKit
Library:Mosquitto
集成方式:pod 'MQTTKit'(官方集成方式有誤)
使用:
#import <MQTTKit.h>
//這里的clientID 類似于登錄的賬號
MQTTClient *client = [[MQTTClient alloc] initWithClientId:clientID];
// connect to the MQTT server
//Host 類似于服務器的IP 默認端口號1883,可以點擊進去修改
[self.client connectToHost:@"iot.eclipse.org"
completionHandler:^(NSUInteger code) {
if (code == ConnectionAccepted) {
// when the client is connected, subscribe to the topic to receive message.
//topic主題 是和服務端溝通定的
[self.client subscribe:@"/MQTTKit/example"
withCompletionHandler:nil];
}
}];
//取消訂閱主題
[self.client unsubscribe:@"/MQTTKit/example" withCompletionHandler:^{
}];
//主動發送消息給服務端
[self.client publishString:@"Hello, MQTT"
toTopic:@"/MQTTKit/example"
withQos:AtMostOnce
retain:NO
completionHandler:^(int mid) {
NSLog(@"message has been delivered");
}];
//主動和服務端斷開
[self.client disconnectWithCompletionHandler:^(NSUInteger code) {
// The client is disconnected when this completion handler is called
NSLog(@"MQTT client is disconnected");
}];
//接收數據 只能通過Block回傳接收
[self.client setMessageHandler:^(MQTTMessage* message)
{
dispatch_async(dispatch_get_main_queue(), ^{
//接收到消息,更新界面時需要切換回主線程
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:message.payload options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@",dic);
});
}];
以上呢是 MQTTKit 中主要的方法,博主項目中集成持續使用了一個月時間,穩定性一般,由于這個庫兩年前已經停止維護,所以在項目有時會發生對象被誤釋放導致程序崩潰,這種幾率還是很低的。
還有需要說明的是MQTTKit 是自動重連機制,采用的是blcok回調機制,在異步線程中執行。
2.MQTTClient
https://github.com/ckrey/MQTT-Client-Framework
Library:native
集成方式:pod 'MQTTClient'
使用:
#import "MQTTClient.h"
設置<MQTTSessionDelegate>
//初始化一個傳輸類型的實例
MQTTCFSocketTransport *transport = [[MQTTCFSocketTransport alloc] init];
transport.host = @"localhost";
transport.port = 1883;
//創建一個任務
MQTTSession *session = [[MQTTSession alloc] init];
//設置任務的傳輸類型
session.transport = transport;
//設置任務的代理為當前類
session.delegate = self;
//設置登錄賬號
session.clientId = @"clientId";
BOOL isSucess = [session connectAndWaitTimeout:30]; //this is part of the synchronous API
if(isSucess){
//以下部分是訂閱一個主題
[session subscribeToTopic:@"topic" atLevel:2 subscribeHandler:^(NSError *error, NSArray<NSNumber *> *gQoss){
if (error) {
NSLog(@"Subscription failed %@", error.localizedDescription);
} else {
NSLog(@"Subscription sucessfull! Granted Qos: %@", gQoss);
}
}];
}
//接收數據
- (void)newMessage:(MQTTSession *)session
data:(NSData *)data
onTopic:(NSString *)topic
qos:(MQTTQosLevel)qos
retained:(BOOL)retained
mid:(unsigned int)mid {
// this is one of the delegate callbacks
NSLog(@"%@",[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]);
}
//發送數據 this is part of the asynchronous API
[session publishAndWaitData:data
onTopic:@"topic"
retain:NO
qos:MQTTQosLevelAtLeastOnce];
//主動和服務端斷開
[session disconnect];
//取消訂閱主題
[session unsubscribeTopic:@"topic" unsubscribeHandler:^(NSError *error) {
}];
以上是MQTTClient所用到的接口,跟MQTTKit類似,最大的區別是:
1.MQTTClient 連接操作是在主線程中進行,當連接成功以后處理邏輯。
2.MQTTClient中使用代理的方式接收數據,在主線程中,MQTTKi需要接收到數據后回調主線程。
3..MQTTClient一直處于維護中,可靠性高,并且提供很多好用的接口。
個人感覺MQTTClient 比較靠譜,后期項目中會考慮更換MQTTKit。MQTT在ios中常用于項目中的消息推送,對于一些做客戶端與服務器雙向通訊的小伙伴可以嘗試這種解決方案,我們在使用APNS消息推送中丟包率會影響項目的實際體驗,MQTT是一種不錯的代替方案!
來自:http://www.jianshu.com/p/bcf0251dc181