MQTT(MessageQueueing Telemetry Transport Protocol)的全稱是消息隊列遙感傳輸協議的縮寫,是由IBM公司推出的一種基於輕量級代理的發佈/訂閱模式的消息傳輸協議,運行在TCP協議棧之上,爲其提供有序、可靠、雙向鏈接的網絡鏈接保證。因爲其開放、簡單和易於實現因此可以應用在資源受限的環境中,對於M2M和物聯網應用程序來講是一個至關不錯的選擇。服務器
MQTT協議是針對以下狀況設計的:網絡
M2M(Machine to Machine) communication,機器端到端通訊,好比傳感器之間的數據通信 由於是Machine to Machine,須要考慮: Machine,或者叫設備,好比溫度傳感器,硬件能力很弱,協議要考慮儘可能小的資源消耗,好比計算能力和存儲等 M2M多是無線鏈接,網絡不穩定,帶寬也比較小session
MQTT的特色:架構
0表明「至多一次」,消息發佈徹底依賴底層 TCP/IP 網絡。會發生消息丟失或重複。這一級別可用於以下狀況,環境傳感器數據,丟失一次讀記錄無所謂,由於不久後還會有第二次發送。app
1表明「至少一次」,確保消息到達,但消息重複可能會發生。框架
2表明「只有一次」,確保消息到達一次。這一級別可用於以下狀況,在計費系統中,消息重複或丟失會致使不正確的結果。 備註:因爲服務端採用Mosca實現,Mosca目前只支持到QoS 1eclipse
若是發送的是臨時的消息,例如給某topic全部在線的設備發送一條消息,丟失的話也無所謂,0就能夠了(客戶端登陸的時候要指明支持的QoS級別,同時發送消息的時候也要指明這條消息支持的QoS級別),若是須要客戶端保證能接收消息,須要指定QoS爲1,若是同時須要加入客戶端不在線也要能接收到消息,那麼客戶端登陸的時候要指定session的有效性,接收離線消息須要指定服務端要保留客戶端的session狀態。async
mqtt基於訂閱者模型架構,客戶端若是互相通訊,必須在同一訂閱主題下,即都訂閱了同一個topic,客戶端之間是沒辦法直接通信的。訂閱模型顯而易見的好處是羣發消息的話只須要發佈到topic,全部訂閱了這個topic的客戶端就能夠接收到消息了。ide
發送消息必須發送到某個topic,重點說明的是無論客戶端是否訂閱了該topic均可以向topic發送了消息,還有若是客戶端訂閱了該主題,那麼本身發送的消息也會接收到。ui
$ 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
#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
#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); }