[iOS 项目中用的MQTT以及注意点记录]

目前项目中用的是这个MQTT处理,,没有采用GithHub上的MQTTClient
但是用下来发现,项目中目前使用的这个方案也是可以满足需要的

目前使用的是这个
iOS,MQTTClient使用
http://www.cnblogs.com/douniwanxia/p/6580175.html

下面记录一下问题

MQTT的断开;

问题一

无论是什么情况的断开,
MQTTSession的代理方法

-(void)handleEvent:(MQTTSession *)session event:(MQTTSessionEvent)eventCode error:(NSError *)error;

都会返回closed这样的错误码
这时候只需要执行重新连接即可
- (void)connect{
[_mqttSession connect];
}

但是稍微注意的是,最好手工控制一下重连的延迟时间,不然在处于断网的情况下,mqtt会不断重连,不断回调错误码,然后又崩溃风险,加一下延迟执行重连,目前没有发现崩溃可能.

问题二

iOS系统,在mqtt进入后台以后,MQTT好像就不工作了,回调什么的也没有,只能重新打开app以后,才会执行回调,才能重新连接,不知道大家有没有好点的办法解决,先记录一下, 等找到办法了再补充

问题三(诡异的线程卡顿)

1.切换为4G网络后,登录App同时登陆MQTT,在订阅消息的时候线程卡主!!!!!
明确一个事实:

在订阅消息时,必须在主线程,否则不会回调获取消息

网络情况不好时,就容易在订阅消息这一步卡主主线程,导致UI线程卡顿.

    dispatch_async(dispatch_get_main_queue(), ^{
            // [self.mqttSession subscribeTopic:_topic];
           [self.mqttSession subscribeToTopic:_topic atLevel:MQTTQosLevelAtLeastOnce];
        });

解决办法就是超时时间设置小一点就好!!!!!!!!

[self.mqttSession connectAndWaitTimeout:1];

补充一个坑

使用MQTTClient的SDK时,为了离线能获取未推送的消息, 我设置了
clean:false ,结果导致App挂起一段时间后,使用同样的clientID再去获取推送时, (App重新唤起,重新连接,但就是收不到推送).
设置clean:true 则问题解决.

不知是否后端配置的代码是否存在问题,如果收不到推送,可以先尝试clean掉session.方便排除问题

补充第二个坑

App多次退出登录 再登陆以后, MQTT推送的回调回调多次

2018-01-26 17:46:43.636585+0800 sandbao[3917:1696336] [MQTTSession] checkDup f974c1662eed04a4066deb33c61cca12 @1516960004

后来的解决办法是

/**
 关闭MQTT
 */
- (void)closeMQTT{

    //避免删除kvo异常
    @try{
        //清除kvo监听
        [self.manager removeObserver:self forKeyPath:@"state"];
    }
    @catch(NSException *exception){

    }

    //关闭连接 - 触发监听(有可能关成功,测试出有关失败的可能)
    [self.manager disconnect];

}

在关闭MQTT连接的时候,不要clean掉 self.manager = nil;

而是在App重新连接的时候, 替换session的clientID

self.manager.session.clientId = clientID;
[self.manager connectToLast];

查看 MQTTSession.m

在 执行 [self.manager connectToLast];方法后,
最终会执行到以下方法,

- (void)connect {

    if (MQTTStrict.strict &&
        self.clientId && self.clientId.length < 1 &&
        !self.cleanSessionFlag) {
        NSException* myException = [NSException
                                    exceptionWithName:@"clientId must be at least 1 character long if cleanSessionFlag is off"
                                    reason:[NSString stringWithFormat:@"clientId length = %lu",
                                            (unsigned long)[self.clientId dataUsingEncoding:NSUTF8StringEncoding].length]
                                    userInfo:nil];
        @throw myException;
    }
   ....
    self.transport.delegate = self;
    [self.transport open];
}

所以,在这个方法执行之前 切换其 self.clientID 即可重新连接,并不需要每次都重新登录.

注意 - MQTTClient更新以后 connect方法由变化

新方法增加了几个参数,应该是支持 配置安全策略 / 证书 /MQTTSSLSecurityPolicy

具体参考这篇文章

(iOS)MQTT连接 遗嘱 双向认证

      [self.manager
         connectTo:kIP
         port:kPort
         tls:false
         keepalive:30
         clean:true
         auth:true
         user:kMqttuserNmae
         pass:kMqttpasswd
         will:false
         willTopic:@""
         willMsg:nil
         willQos:MQTTQosLevelExactlyOnce
         willRetainFlag:false
         withClientId:clientID
         securityPolicy:nil
         certificates:nil
         protocolLevel:MQTTProtocolVersion0
         connectHandler:^(NSError *error) {

         }];
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值