ios MQTT协议及通讯的解决方案

TuyetDeRoug 8年前
   <p style="text-align:center"><img src="https://simg.open-open.com/show/1a5b52f66891f3a78d6cad7492ce7abc.jpg"></p>    <p style="text-align:center">MQTT关系图</p>    <p>做消息推送有一段时间了,想和大家分享一下通过MQTT消息推送的解决方案。</p>    <h2><strong>一、MQTT简介</strong></h2>    <p>MQTT(Message Queuing Telemetry Transport,消息队列遥测传输)是IBM开发的一个即时通讯协议,该协议支持所有平台,也就是说不论什么平台都可以使用集成此协议,网上大多说该协议用于物联网,,有可能成为物联网的重要组成部分。几乎可以把所有联网物品和外部连接起来,被用来当做传感器和致动器(比如通过推ter让房屋联网)的通信协议。</p>    <h2><strong>二、MQTT特点</strong></h2>    <p>MQTT协议是为大量计算能力有限,且工作在低带宽、不可靠的网络的远程传感器和控制设备通讯而设计的协议,它具有以下主要的几项特性:</p>    <p>1、使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合;</p>    <p>2、对负载内容屏蔽的消息传输;</p>    <p>3、使用 TCP/IP 提供网络连接;</p>    <p>4、有三种消息发布服务质量:</p>    <p>“至多一次”,消息发布完全依赖底层 TCP/IP 网络。会发生消息丢失或重复。这一级别可用于如下情况,环境传感器数据,丢失一次读记录无所谓,因为不久后还会有第二次发送。</p>    <p>“至少一次”,确保消息到达,但消息重复可能会发生。</p>    <p>“只有一次”,确保消息到达一次。这一级别可用于如下情况,在计费系统中,消息重复或丢失会导致不正确的结果。</p>    <p>5、小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;</p>    <h2><strong>三、ios端 MQTT集成解决方案</strong></h2>    <p>我使用过两个github上的三方库</p>    <p>1.MQTTKit</p>    <p><a href="/misc/goto?guid=4959716484227695778" rel="nofollow,noindex">https://github.com/mobile-web-messaging/MQTTKit</a></p>    <p>Library:Mosquitto</p>    <p>集成方式:pod 'MQTTKit'(官方集成方式有误)</p>    <p>使用:</p>    <pre>  <code class="language-objectivec">#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);                       });                   }];</code></pre>    <p>以上呢是 MQTTKit 中主要的方法,博主项目中集成持续使用了一个月时间,稳定性一般,由于这个库两年前已经停止维护,所以在项目有时会发生对象被误释放导致程序崩溃,这种几率还是很低的。</p>    <p>还有需要说明的是MQTTKit 是自动重连机制,采用的是blcok回调机制,在异步线程中执行。</p>    <p>2.MQTTClient</p>    <p><a href="/misc/goto?guid=4959716484321298185" rel="nofollow,noindex">https://github.com/ckrey/MQTT-Client-Framework</a></p>    <p>Library:native</p>    <p>集成方式:pod 'MQTTClient'</p>    <p>使用:</p>    <pre>  <code class="language-objectivec">#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) {        }];</code></pre>    <p>以上是MQTTClient所用到的接口,跟MQTTKit类似,最大的区别是:</p>    <p>1.MQTTClient 连接操作是在主线程中进行,当连接成功以后处理逻辑。</p>    <p>2.MQTTClient中使用代理的方式接收数据,在主线程中,MQTTKi需要接收到数据后回调主线程。</p>    <p>3..MQTTClient一直处于维护中,可靠性高,并且提供很多好用的接口。</p>    <p>个人感觉MQTTClient 比较靠谱,后期项目中会考虑更换MQTTKit。MQTT在ios中常用于项目中的消息推送,对于一些做客户端与服务器双向通讯的小伙伴可以尝试这种解决方案,我们在使用APNS消息推送中丢包率会影响项目的实际体验,MQTT是一种不错的代替方案!</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/bcf0251dc181</p>    <p> </p>