iOS MQTT 使用

97 篇文章 0 订阅
79 篇文章 2 订阅

开发中我们经常使用到长连接,需要时时获取到最新数据状态,常用的时时获取最新状态的方法用很多,但是开发中一般都会使用socket长连接。针对这个也有一个库CocoaAsyncSocket,对socket也已经封装的很好,我们也只需要下载对应的库就可以了,下载链接:

https://github.com/robbiehanson/CocoaAsyncSocket

今天介绍一下MQTT长连接。cocoapods 的使用方法很简单,pod 'MQTTClient' 就可以了,那非cocoapods 到底需要导入那些库呢?

csdn连接

https://download.csdn.net/download/wangqinglei0307/10824049

github连接

https://github.com/ckrey/MQTT-Client-Framework

点击此链接,既可以下载到的MQTT库然后直接将库导入到工程就可以了。

写工程的时候,需要使用ca.crt证书,这个是需要我们去生成的,后台开发人员,都会讲这个文件直接给我们,我们只需要将这个文件直接拽进工程就可以了

还有一个就是MQTT要用到一个topic(字符串类型),这个是一个很重要,需要和服务器统一,我们要靠这个订阅,简单来说就是,我们发送消息和接收消息,可能类型是不同的,都是通过这个topic来决定,你发给第一个topic消息,服务器只会返回第一个topic的消息反馈,这样可以有效管理不同的信息处理

然后就是使用了,首先为了方便使用。我们写一个MQTT 管理类 MQTTManager.h文件

粘贴代码:

MQTTManager.h

#import <Foundation/Foundation.h>

@interface MQTTManager : NSObject

/**
 创建单例,返回始终为一个对象
 
 @return self
 */
+ (MQTTManager *)sharedManager;

#pragma mark - MQTT连接
- (void)userMQTTBind;

#pragma mark - 订阅
- (void)subscribeTopic:(NSString *)topic;

#pragma mark - 发布消息
- (void)sendDataToTopic:(NSString *)topic dict:(NSDictionary *)dict;

#pragma mark - 主动断开
- (void)disconnect;

#pragma mark - 取消订阅
- (void)unsubscribeTopic:(NSString *)topic;

MQTTManager.m文件

复制代码:


#import "MQTTManager.h"
// 导入头文件
#import "MQTTClient.h"
@interface MQTTManager ()<MQTTSessionManagerDelegate,MQTTSessionDelegate>
@property (nonatomic, strong) MQTTSessionManager *sessionManager;
@property (nonatomic, strong) MQTTSession        *mySession;
@property (nonatomic, strong) NSMutableArray     *subArray;
@property (nonatomic, assign) BOOL isDiscontent;
@end

@implementation MQTTManager

/**
 创建单例,返回始终为一个对象
 
 @return self
 */
+ (MQTTManager *)sharedManager{
    static MQTTManager *manager = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        manager = [[self alloc] init];
    });
    return manager;
}

- (MQTTSessionManager*)sessionManager{
    if (_sessionManager == nil) {
        _sessionManager = [[MQTTSessionManager alloc]init];
        _sessionManager.delegate = self;
    }
    return _sessionManager;
}

- (NSMutableArray*)subArray{
    if ( _subArray == nil ) {
        _subArray = [[NSMutableArray alloc]init];
    }
    return _subArray;
}

#pragma mark - 绑定
- (void)userMQTTBind{
    self.mySession = [[MQTTSession alloc]initWithClientId:[NSString stringWithFormat:@"%@@@@%@%@",@"GID_XXX",@"",[NSObject getUserDeviceUUIDString]]
                                                 userName:@"用户名"
                                                 password:@"密码"
                                                keepAlive:60
                                             cleanSession:YES
                                                     will:NO
                                                willTopic:nil
                                                  willMsg:nil
                                                  willQoS:MQTTQosLevelAtLeastOnce
                                           willRetainFlag:NO
                                            protocolLevel:4 // 这块需要注意,代表mqtt版本等级,需要和后台确认一下,否则会出现因为版本等级而导致mqtt无法使用(本人亲自踩过坑)
                                                  runLoop:[NSRunLoop mainRunLoop]
                                                  forMode:nil
                                           securityPolicy:[self customSecurityPolicy]];
    self.isDiscontent = NO;
    self.mySession.delegate = self;
    [self.mySession connectToHost:@"连接的服务器域名或者IP" port:域名 usingSSL:YES];
    [self.mySession addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        switch (self.mySession.status) {
            case MQTTSessionStatusClosed:
                NSLog(@"连接关闭");
                if (!self.isDiscontent) [self.mySession connect]; //这个是为了区分是主动断开还是被动断开。
                break;
            case MQTTSessionStatusConnected:
                NSLog(@"连接成功");
                break;
            case MQTTSessionStatusConnecting:
                NSLog(@"连接中");
                
                break;
            case MQTTSessionStatusError:
                NSLog(@"连接错误");
                
                break;
            case MQTTSessionStatusDisconnecting:
                NSLog(@"正在断开连接");
                
            default:
                break;
        }
}

- (MQTTSSLSecurityPolicy *)customSecurityPolicy{
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"crt"];
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    MQTTSSLSecurityPolicy *securityPolicy = [MQTTSSLSecurityPolicy policyWithPinningMode:MQTTSSLPinningModeNone];
    securityPolicy.allowInvalidCertificates = YES;
    securityPolicy.validatesCertificateChain = YES;
    securityPolicy.validatesDomainName = NO;
    securityPolicy.pinnedCertificates = @[certData];
    return securityPolicy;
}

#pragma mark - 订阅
- (void)subscribeTopic:(NSString *)topic {
    if (self.mySession.status != MQTTSessionStatusConnected  && ![self.subArray containsObject:topic]) {
        [self.subArray addObject:topic];
        return;
    }
    __weak typeof(self) weakSelf = self;
    self.sessionManager.subscriptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:MQTTQosLevelExactlyOnce] forKey:topic];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.mySession subscribeToTopic:topic atLevel:MQTTQosLevelAtLeastOnce subscribeHandler:^(NSError *error, NSArray<NSNumber *> *gQoss) {
                if (error) {
                    NSLog(@"subscribeTopic failed ----- topic = %@ \n %@",topic,error.localizedDescription);
                    [weakSelf.subArray addObject:topic];
                } else {
                    if ([weakSelf.subArray containsObject:topic]) {
                        [weakSelf.subArray removeObject:topic];
                    }
                    NSLog(@"subscribeTopic sucessfull 成功! topic = %@  \n %@",topic,gQoss);
                }
            }];
            
        });
    });
}

#pragma mark - 取消订阅
- (void)unsubscribeTopic:(NSString *)topic {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.mySession unsubscribeTopic:topic unsubscribeHandler:^(NSError *error) {
                if (error) {
                    NSLog(@"unsubscribeTopic failed ----- topic = %@ \n %@",topic,error.localizedDescription);
                } else {
                    NSLog(@"unsubscribeTopic sucessfull 成功! topic = %@ ",topic);
                }
            }];
        });
    });
}

#pragma mark - 发布消息
- (void)sendDataToTopic:(NSString *)topic dict:(NSDictionary *)dict {
    [self.mySession publishJson:dict onTopic:topic];
}

#pragma mark - MQTTSessionDelegate 获取返回内容,与后台协商
- (void)newMessage:(MQTTSession *)session data:(NSData *)data onTopic:(NSString *)topic qos:(MQTTQosLevel)qos retained:(BOOL)retained mid:(unsigned int)mid {
    NSMutableString *string = [[NSMutableString alloc]  initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"thl -----  data = %@ \n thl -----  str = %@ \n -------- topic:%@ --------- \n",data,string,topic);
    
}

- (void)session:(MQTTSession*)session newMessage:(NSData*)data onTopic:(NSString*)topic{
    
}

然后根据我们的需要直接使用就可以了。例如:

粘贴代码:    

    //建立MQTT连接
    
    [[MQTTManager sharedManager]userMQTTBind];
    
    //连接以后发送订阅,订阅名字   (我是第一订阅)
    
    [[MQTTManager sharedManager]subscribeTopic:@"我是第一订阅"];
    
    // 发送订阅信息 (@"我是第一订阅")下的  信息为:@{@"key":@"所传的参数"},信息
    
    [[MQTTManager sharedManager]sendDataToTopic:@"我是第一订阅" dict:@{@"key":@"所传的参数"}];

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王 哪跑!!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值