1.什么是MQTT?MQTT(MessageQueueingTelemetryTransportProtocol)全称是MessageQueueRemoteSensingTransportProtocol的缩写。它是IBM推出的一种基于代理的轻量级发布/订阅模型。运行在TCP协议栈上的报文传输协议为其提供了有序、可靠、双向连接的网络连接保障。由于其开放性、简单性和易于实现,它可以在资源受限的环境中使用,是M2M和IoT应用程序的不错选择。2、为什么要使用MQTT?MQTT协议是为以下几种情况设计的:M2M(MachinetoMachine)通信,机器之间端到端的通信,比如传感器之间的数据通信。因为是MachinetoMachine,需要考虑:Machine,或者叫Devices,比如温度传感器,硬件能力较弱,协议要考虑最小化资源消耗,比如算力和存储。M2M可能是无线连接,网络不稳定,带宽比较小。MQTT的特点:1.发布/订阅消息模式,提供一对多的消息发布,解耦应用。这一点和1很像,这里是列表文本XMPP,但是MQTT的信息冗余比XMPP小很多。2.屏蔽负载内容的消息传输。3.使用TCP/IP提供网络连接。主流的MQTT是基于TCP连接进行数据推送的,但是也有基于UDP的版本,叫做MQTT-SN。由于这两个版本基于不同的连接方式,其优缺点自然是不同的。4、三种消息传输方式QoS:0表示“至多一次”,消息的发布完全依赖于底层的TCP/IP网络。可能会发生消息丢失或重复。这个级别可以用在以下几种情况,环境传感器数据,一条读记录丢了也没关系,因为近期会有第二次发送。1代表“至少一次”,保证消息到达,但可能会出现消息重复。2代表“onlyonce”,确保消息到达一次。此级别可用于重复或丢失消息可能导致计费系统产生错误结果的情况。备注:由于服务端是Mosca实现的,Mosca目前只支持QoS1,如果发送临时消息,比如给某个topic的所有在线设备发送消息,丢了也无所谓,0是fine(客户端登录时需要指定支持的QoS等级,发送消息时也要指定该消息支持的QoS等级)。如果需要客户端保证能收到消息,则需要指定QoS为1,如果需要同时离线加入客户端,还必须指定如果消息可以接收,则客户端必须指定登录时会话的有效性。要接收离线消息,必须指定服务器保留客户端的会话状态。Mqtt基于订阅者模型架构。如果客户端之间相互通信,则必须在同一个订阅主题下,即都订阅同一个主题。客户无法直接沟通。订阅模式的一个明显优势是,如果发送群消息,只需要发布到主题,所有订阅该主题的客户端都可以收到消息。发送消息必须发送到某个主题。关键是无论客户端是否订阅主题,都可以向主题发送消息。如果客户端订阅了主题,自己发送的消息也会被接收到。5.开销很小的小传输(定长头是2字节),协议交换被最小化以减少网络流量。这就是为什么在介绍中说它非常适合“在物联网领域,传感器和服务器之间的通信,以及信息采集”。要知道嵌入式设备的计算能力和带宽都比较弱,使用这种协议来传输消息是比较合适的。但仅此而已。6、利用LastWillandTestament特性通知相关方客户端异常中断机制。LastWill:即最后遗嘱机制,用于通知同一主题下的其他设备,发送最后遗嘱的设备已断开连接。遗嘱:遗嘱机制,功能类似于LastWill。3、怎么使用MQTT在mac上搭建MQTT服务器$brewinstallmosquitto等待下载完成,服务会自动运行起来mosquittohasbeeninstalledwithadefaultconfigurationfile.Youcanmakechangestotheconfigurationbyediting:/usr/local/etc/mosquitto/mosquitto.confTohavelaunchdstartmosquittonowandrestartatlogin:brewservicesstartmosquittoOr,ifyoudon'twant/needabackgroundserviceyoucanjustrun:mosquitto-c/usr/local/etc/mosquitto/mosquitto.confiOS客户端注册#import"ViewController.h"#definekMQTTServerHost@"iot.eclipse.org"#definekTopic@"MQTTExample/Message"@interfaceViewController()@property(weak,nonatomic)IBOutletUILabel*showMessage;@property(nonatomic,strong)MQTTClient*client;@end@implementationViewController-(void)viewDidLoad{[superviewDidLoad];//1.app登录后后台返回name+password+topic//2.name+password用于连接host//3.topic用于订阅主题UILabel*tempShowMessage=self.showMessage;NSString*clientID=[UIDevicecurrentDevice].identifierForVendor.UUIDString;self.client=[[MQTTClientalloc]initWithClientId:clientID];//连接到服务器后,会通过block返回连接结果码,然后执行这个代码块//这个接口是修改后的接口,修改后抛出name+password[self.clientconnectToHost:kMQTTServerHostandName:@"cbt"andPassword:@"1223"completionHandler:^(MQTTConnectionReturnCodecode){if(code==ConnectionAccepted)//连接成功{//订阅[self.clientsubscribe:kTopicwithCompletionHandler:^(NSArray*grantedQos){//TheclientiseffectivelysubscribedtothetopicwhenthiscompletionhandleriscalledNSLog(@"subicsc%",kTopic);NSLog(@"return:%@",grantedQos);}];}}];//MQTTMessage中的数据是二进制接收的,这里框架封装成astring[self.clientsetMessageHandler:^(MQTTMessage*message){dispatch_async(dispatch_get_main_queue(),^{//接收消息,更新接口时需要切换回主线程tempShowMessage.text=message.payloadString;});}];}-(void)dealloc8{//disconnecttheMQTTclient[self.clientdisconnectWithCompletionHandler:^(NSUIntegercode){//TheclientisdisconnectedwhenthiscompletionhandleriscalledNSLog(@"MQTTisdisconnected");}];}@endserver向客户端推送消息#import"ViewController.h"#import"MQTTKit.h"#definekMQTTServerHost@"iot.eclipse.org"#definekTopic@"MQTTExample/Message"@interfaceViewController()@property(weak,nonatomic)IBOutletUITextField*pushMessage;@property(nonatomic,strong)MQTTClient*client;@end@implementationViewController-(void)viewDidLoad{[superviewDidLoad];NSString*clientID=[UIDevicecurrentDevice].identifierForVendor.UUIDString;self.client=[[MQTTClientalloc]initWithClientId:clientID];[self.clientconnectToHost:kMQTTServerHostandName:@"cbt"andPassword:@"1223"completionHandler:^(MQTTConnectionReturnCodecode){if(code==ConnectionAccepted){NSLog(@"服务器启动成功");}}];}-(IBAction)push:(id)sender{NSString*payload=self.pushMessage.text;[self.clientpublishString:payloadtoTopic:kTopicwithQos:AtMostOnceretain:YEScompletionHandler:nil];NSLog(@"推送内容:%@",payload);}
