MQTT 入门

#1.介绍 关于MQTT就不需过多的介绍,网上一大堆。不过支持iOS 推荐如下库 1.MQTTKit--基于Mosquitto 不过长时间未更新了 2.MQTT-Client-Framework--基于iOS 原生 #2.采坑记录 本文着重介绍MQTT-Client-Framework的使用和注意事项。 ##1.关于初始化git

//带证书
    NSString *certificate = [[NSBundle mainBundle]pathForResource:@"ca" ofType:@"cer"];
    MQTTWebsocketTransport *transport = [[MQTTWebsocketTransport alloc]init];
     transport.host = self.host;
     transport.port = self.port;
     transport.tls = YES;
     //坑1---release 下默认是NO, 若是你的证书是自签名证书须要设置为YES ,不然你的release版本将没法经过证书验证,提示 shakehandfield 。
    transport.allowUntrustedCertificates = YES;
    //坑2---初始化必需要在主线程当中,由于 session的init 方法会默认建立一个 runloop 源码中使用的是 currentRunloop. 这个runloop 是用于 encode 和 decode。若是放在子线程将没法收到encode 和 decode的回调。
     self.session = [[MQTTSession alloc] initWithClientId:self.uuid userName:self.username password:self.password keepAlive:50 cleanSession:YES];
     self.session.transport = transport;
     self.session.delegate = self;
     self.session.certificates = @[[NSData dataWithContentsOfFile:certificate]];
复制代码

##2.发布 坑3---放在子线程,过多的数据读写所有放在主线程会阻塞。 ##3.取消订阅和订阅 ##4.关于代理github

//有新消息的回调
- (void)newMessage:(LDSMQTTSession *)session
              data:(NSData *)data
           onTopic:(NSString *)topic
               qos:(MQTTQosLevel)qos
          retained:(BOOL)retained
               mid:(unsigned int)mid;
//链接状态改变的回调
- (void)handleEvent:(LDSMQTTSession *)session event:(LDSMQTTSessionEvent)eventCode error:(NSError *)error;

//链接被拒绝的回调--用于链接被踢掉,或证书没法验证经过等缘由查询,可作帐号密码校验
- (void)connectionRefused:(LDSMQTTSession *)session error:(NSError *)error;

其余不过多介绍了
复制代码

##4.关于断开重连策略web

//  重连机制
-(void) reConnect {
    //   2^5=64
    if (reConnecTime>64) {

        NSLog(@"reconnect timeout !");
        if (_timer) {
            dispatch_cancel(_timer);
            _timer = nil;
        }
        return;
    }
    if (_timer==nil) {
        _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
        dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
        dispatch_source_set_event_handler(_timer, ^{
            reConnecTimeCount++;
            if (reConnecTimeCount==reConnecTime) {
                [self.session disconnect];
                [self connect];
                reConnecTimeCount = 0;
                dispatch_cancel(_timer);
                _timer = nil;
            }
        });
        dispatch_resume(_timer);
    }
    
    NSLog(@"重连间隔时间 %f",reConnecTime);
    reConnecTime *=2;
}
复制代码

##5.请求超时和重试机制 目前我的想到2种解决方案,1.由每一个请求本身去检查本身是否请求超时,2.由转换层统一处理。 我的更倾向于方案2.bash

//遍历我请求等待队列的req 
for (int i = (int)ws.routingRequests.count - 1; i >= 0; i --) {

  LDSSktBaseRequest *req = nil;
   req = [ws.routingRequests objectAtIndex:i];
   //超时处理
   若是req 的请求到期时间到当前时间的时间差 + (req 的超时时间*req 的重试次数) <0 ,那么请求超时
 if ([req.timeoutDate timeIntervalSinceNow]<0-req.timeIntervalOut*req.retryCount) {
        if (req.delegate && [req.delegate                 respondsToSelector:@selector(ldsSktBaseRequestServiceDidReceiveResponse:error:)]) {
            [req.delegate ldsSktBaseRequestServiceDidReceiveResponse:req error:[NSError errorWithDomain:@"com.ldsSocket" code:-999 userInfo:@{NSLocalizedDescriptionKey:     @"Request Timeout"}]];
            [ws removeRequest:req];
            NSLog(@"Request Timeout\n %@ ",[req params]);
            continue;
            }
        }
   }
复制代码

##6.请求等待队列和请求发送等待队列 每一个MQTT session 我维护了一个请求等待队列(等待回复的请求,若是当前链接状态不是链接成功 且 等待发送队列不包含,就放入发送队列,不然加入回复队列中)和一个请求等待发送队列(因链接断开或还未开始链接时发送的请求,一旦链接成功就把该队列的请求所有发出)session

相关文章
相关标签/搜索