iOS開發之MQTT探究

ErnPratt 7年前發布 | 13K 次閱讀 MQTT iOS開發 移動開發

1、 什么是MQTT?

MQTT(MessageQueueing Telemetry Transport Protocol)的全稱是消息隊列遙感傳輸協議的縮寫,是由IBM公司推出的一種基于輕量級代理的發布/訂閱模式的消息傳輸協議,運行在TCP協議棧之上,為其提供有序、可靠、雙向連接的網絡連接保證。由于其開放、簡單和易于實現所以能夠應用在資源受限的環境中,對于M2M和物聯網應用程序來說是一個相當不錯的選擇。

2、 為什么要用MQTT?

MQTT協議是針對如下情況設計的:

M2M(Machine to Machine) communication,機器端到端通信,比如傳感器之間的數據通訊 因為是Machine to Machine,需要考慮: Machine,或者叫設備,比如溫度傳感器,硬件能力很弱,協議要考慮盡量小的資源消耗,比如計算能力和存儲等 M2M可能是無線連接,網絡不穩定,帶寬也比較小

MQTT的特點:

1.發布/訂閱消息模式,提供一對多的消息發布,解除應用程序耦合。這一點很類似于1. 這里是列表文本XMPP,但是MQTT的信息冗余遠小于XMPP.

2.對負載內容屏蔽的消息傳輸。

3.使用TCP/IP提供網絡連接。主流的MQTT是基于TCP連接進行數據推送的,但是同樣有基于UDP的版本,叫做MQTT-SN。這兩種版本由于基于不同的連接方式,優缺點自然也就各有不同了。

4.三種消息傳輸方式QoS:

  • 0代表“至多一次”,消息發布完全依賴底層 TCP/IP 網絡。會發生消息丟失或重復。這一級別可用于如下情況,環境傳感器數據,丟失一次讀記錄無所謂,因為不久后還會有第二次發送。
  • 1代表“至少一次”,確保消息到達,但消息重復可能會發生。
  • 2代表“只有一次”,確保消息到達一次。這一級別可用于如下情況,在計費系統中,消息重復或丟失會導致不正確的結果。 備注:由于服務端采用Mosca實現,Mosca目前只支持到QoS 1
  • 如果發送的是臨時的消息,例如給某topic所有在線的設備發送一條消息,丟失的話也無所謂,0就可以了(客戶端登錄的時候要指明支持的QoS級別,同時發送消息的時候也要指明這條消息支持的QoS級別),如果需要客戶端保證能接收消息,需要指定QoS為1,如果同時需要加入客戶端不在線也要能接收到消息,那么客戶端登錄的時候要指定session的有效性,接收離線消息需要指定服務端要保留客戶端的session狀態。
  • mqtt基于訂閱者模型架構,客戶端如果互相通信,必須在同一訂閱主題下,即都訂閱了同一個topic,客戶端之間是沒辦法直接通訊的。訂閱模型顯而易見的好處是群發消息的話只需要發布到topic,所有訂閱了這個topic的客戶端就可以接收到消息了。
  • 發送消息必須發送到某個topic,重點說明的是不管客戶端是否訂閱了該topic都可以向topic發送了消息,還有如果客戶端訂閱了該主題,那么自己發送的消息也會接收到。

5.小型傳輸,開銷很小(固定長度的頭部是2字節),協議交換最小化,以降低網絡流量。這就是為什么在介紹里說它非常適合“在物聯網領域,傳感器與服務器的通信,信息的收集”,要知道嵌入式設備的運算能力和帶寬都相對薄弱,使用這種協議來傳遞消息再適合不過了。

6.使用Last Will和Testament特性通知有關各方客戶端異常中斷的機制。Last Will:即遺言機制,用于通知同一主題下的其他設備發送遺言的設備已經斷開了連接。Testament:遺囑機制,功能類似于Last Will 。

3、 怎么使用MQTT

在mac上搭建MQTT服務器

$ brew install mosquitto 

等待下載完成,服務會自動運行起來

mosquitto has been installed with a default configuration file. 
You can make changes to the configuration by editing:  
/usr/local/etc/mosquitto/mosquitto.conf  
To have launchd start mosquitto now and restart at login:  
brew services start mosquitto  
Or, if you don't want/need a background service you can just run:  
mosquitto -c /usr/local/etc/mosquitto/mosquitto.conf 

iOS client注冊

#import "ViewController.h" 
 
#define kMQTTServerHost @"iot.eclipse.org" 
#define kTopic @"MQTTExample/Message" 
 
@interface ViewController () 
@property (weak, nonatomic) IBOutlet UILabel *showMessage; 
@property (nonatomic, strong) MQTTClient *client; 
@end 
 
@implementation ViewController 
 
- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
 
    //1.在app登錄后,后臺返回 name+password+topic 
 
    //2.name+password用于連接主機 
 
    //3.topic 用于訂閱主題 
 
 
    UILabel *tempShowMessage = self.showMessage; 
 
    NSString *clientID = [UIDevice currentDevice].identifierForVendor.UUIDString; 
 
    self.client = [[MQTTClient alloc] initWithClientId:clientID]; 
 
    //連接服務器  連接后,會通過block將連接結果code返回,然后執行此段代碼塊 
 
    //這個接口是修改過后的接口,修改后拋出了name+password 
    [self.client connectToHost:kMQTTServerHost andName:@"cbt" andPassword:@"1223" completionHandler:^(MQTTConnectionReturnCode code) { 
        if (code == ConnectionAccepted)//連接成功 
        { 
            // 訂閱 
            [self.client subscribe:kTopic withCompletionHandler:^(NSArray *grantedQos) { 
                // The client is effectively subscribed to the topic when this completion handler is called 
                NSLog(@"subscribed to topic %@", kTopic); 
                NSLog(@"return:%@",grantedQos); 
            }]; 
        } 
    }]; 
 
 
    //MQTTMessage  里面的數據接收到的是二進制,這里框架將其封裝成了字符串 
    [self.client setMessageHandler:^(MQTTMessage* message) 
    { 
        dispatch_async(dispatch_get_main_queue(), ^{ 
            //接收到消息,更新界面時需要切換回主線程 
            tempShowMessage.text= message.payloadString; 
        }); 
    }];   
 
} 
 
 
- (void)dealloc8 
{ 
    // disconnect the MQTT client 
    [self.client disconnectWithCompletionHandler:^(NSUInteger code) 
    { 
        // The client is disconnected when this completion handler is called 
        NSLog(@"MQTT is disconnected"); 
    }]; 
} 
@end 

server向client推送消息

#import "ViewController.h" 
#import "MQTTKit.h" 
 
 
#define kMQTTServerHost @"iot.eclipse.org" 
#define kTopic @"MQTTExample/Message" 
@interface ViewController () 
@property (weak, nonatomic) IBOutlet UITextField *pushMessage; 
@property (nonatomic, strong) MQTTClient *client; 
@end 
 
@implementation ViewController 
 
- (void)viewDidLoad { 
    [super viewDidLoad]; 
 
 
    NSString *clientID = [UIDevice currentDevice].identifierForVendor.UUIDString; 
 
    self.client = [[MQTTClient alloc] initWithClientId:clientID]; 
    [self.client connectToHost:kMQTTServerHost andName:@"cbt" andPassword:@"1223" completionHandler:^(MQTTConnectionReturnCode code) { 
        if (code == ConnectionAccepted) 
        { 
            NSLog(@"服務器啟動成功"); 
        } 
    }]; 
 
 
} 
 
- (IBAction)push:(id)sender { 
    NSString* payload = self.pushMessage.text; 
    [self.client publishString:payload 
                       toTopic:kTopic 
                       withQos:AtMostOnce 
                        retain:YES 
             completionHandler:nil]; 
    NSLog(@"推送內容:%@",payload); 
} 

 

來自:http://mobile.51cto.com/iphone-531136.htm

 

 本文由用戶 ErnPratt 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!