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

本文分享了iOS应用中MQTT协议的使用经验,包括连接管理、断开重连策略及后台保持活动的技巧,并解决了线程卡顿等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目前项目中用的是这个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) {

         }];
### 手机应用读取 MQTT 数据教程 为了实现手机应用读取 MQTT 数据的功能,可以采用多种方式和技术栈来完成这一目标。以下是基于 Android 和 iOS 平台的解决方案。 #### 1. 使用 Paho MQTT 客户端库 (Android) Paho 是 Eclipse 提供的一个开源项目,支持多平台下的 MQTT 实现。对于 Android 应用开发来说,可以通过集成 Paho 的 Java 版本库来轻松实现 MQTT 功能。 ##### 添加依赖项 在 `build.gradle` 文件中添加以下依赖项: ```gradle implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5' implementation 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1' ``` ##### 初始化 MQTT 客户端并订阅主题 下面是一段用于初始化 MQTT 客户端并订阅指定主题的代码示例: ```java import org.eclipse.paho.android.service.MqttAndroidClient; import org.eclipse.paho.client.mqttv3.IMqttActionListener; import org.eclipse.paho.client.mqttv3.IMqttToken; public class MqttManager { private static final String BROKER_URL = "tcp://your-broker-address.com"; private static final String CLIENT_ID = "YourClientId"; public void connect(MqttAndroidClient client) { try { IMqttToken token = client.connect(); token.setActionCallback(new IMqttActionListener() { @Override public void onSuccess(IMqttToken asyncActionToken) { System.out.println("Connected to broker"); subscribeToTopic(client); } @Override public void onFailure(IMqttToken asyncActionToken, Throwable exception) { System.err.println("Failed to connect to broker"); } }); } catch (Exception e) { e.printStackTrace(); } } private void subscribeToTopic(MqttAndroidClient client) { try { client.subscribe("test/topic", 0); // 订阅主题 test/topic } catch (Exception e) { e.printStackTrace(); } } } ``` 上述代码实现了与 MQTT Broker 连接以及订阅特定主题的操作[^1]。 --- #### 2. 使用 CocoaMQTT 或 HiveMQ Client Library (iOS) 针对 iOS 开发者,可以选择使用 **CocoaMQTT** 或其他类似的第三方框架来快速构建具备 MQTT 支持的应用程序。 ##### 集成 CocoaPods 通过 CocoaPods 来安装 CocoaMQTT,在 Podfile 中加入如下内容: ```ruby pod 'CocoaMQTT', '~> 1.8.0' ``` 执行命令以更新依赖关系: ```bash pod install ``` ##### 创建 MQTT 客户端实例 创建一个简单的 Swift 类用来管理 MQTT 客户端逻辑: ```swift import UIKit import CocoaMQTT class ViewController: UIViewController, CocoaMQTTDelegate { let mqttClient = CocoaMQTT(clientID: "SwiftApp-\(UUID().uuidString)", host: "your-mqtt-host", port: 1883) override func viewDidLoad() { super.viewDidLoad() mqttClient.delegate = self do { try mqttClient.connect() } catch { print("Error connecting to MQTT server.") } } func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) { if ack == .accept { mqttClient.subscribe("test/topic", qos: .qos1) } } func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) { print("Received Message: \(message.string ?? "")") } } ``` 此代码片段展示了如何配置和运行一个基本的 MQTT 客户端,并处理来自订阅主题的消息[^4]。 --- #### 性能对比分析 相比于传统的 HTTP 请求机制,MQTT 在物联网设备间通信方面具有显著的优势。它不仅减少了网络流量开销,还大幅降低了电池消耗率。具体而言,当发送相同量级的数据包时,HTTP 方法可能需要传输约 50 倍于 MQTT 报文长度的信息;而在能耗测试中发现,接收模式下 MQTT 能耗仅为 HTTP 的百分之一,而发送操作则为后者的大致十分之一水平[^2]。 --- #### 注意事项 - 确保所选 MQTT Broker 地址和服务可用性良好。 - 对敏感数据采取加密措施保护隐私安全。 - 测试阶段建议启用日志记录功能以便调试排查问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值