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); }