美文网首页iOS杂记
iOS mqtt & protobuf(三) 合体

iOS mqtt & protobuf(三) 合体

作者: Avalanching | 来源:发表于2019-03-30 14:51 被阅读0次

    protobuf&Mqtt

    1.简单来说就是将Data扔mqtt,然后发送出去就行了!!!

    成果展示

    启动服务器

    image.png

    Demo演示

    mqttGIF.gif

    具体代码

    CocoaPods导入需要的SDK

    1.Protobuf是protobuf的依赖库
    2.MQTTClient是一个开源的Mqtt库,包括链接,订阅,发布消息,接收消息等等(只要站在巨人肩膀上开发就好了,除非你是研发型的公司,需要自己去研发一套协议或者一套新的框架)。
    pod 'Protobuf'
    pod 'MQTTClient'
    
    3.创建一个通讯管理类(管理链接,中断链接,接收和发送消息)

    注意:这里仅作为展示,不做过多的处理,需要做成一个完整的项目还需要更多的东西

    //
    //  MqttManager.h
    //  MQTTDemo
    //
    //  Created by Avalanching on 2019/3/27.
    //  Copyright © 2019 Avalanching. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import <MQTTClient/MQTTClient.h>
    #import "MQTTUserInfo.h"
    #import "MqttMessageBody.pbobjc.h"
    
    typedef NS_ENUM(NSInteger, MQTTConnectionCode) {
        MQTTConnectionCodeDidConnection
    };
    
    @protocol AVAMqttManagerDelegate <NSObject>
    
    /**
     @method sendMessageCallBackWithBool:message:
     @abstrac 发送回调
     @discussion 回调结果是否发送成功了
     @param flag 发送结果
     @param body 发送的信息
     */
    - (void)sendMessageCallBackWithBool:(BOOL)flag message:(MqttMessageBody *)body;
    
    /**
     @method newMessageArrival:
     @abstrac 收到新的信息
     @discussion 收到信息的回调
     @param message 发送的信息
     */
    - (void)newMessageArrival:(MqttMessageBody *)message;
    
    @end
    
    @interface MqttManager : NSObject
    
    // 登陆信息
    @property (nonatomic, strong, readonly) MQTTUserInfo * userinfo;
    
    // 终端连接回调
    @property (nonatomic, copy, readonly) BOOL (^interruptblock)(MQTTConnectionCode code, NSString *msg);
    
    /**
     @method shareManager
     @abstrac 获取一个管理者单例对象
     @discussion 用来管理MQTT的绑定,订阅,链接,中断,接收,发送
     @result MqttManager / NULL (instancetype 仅返回值,告诉编译器不报异常)
     */
    + (instancetype)shareManager;
    
    /**
     @method loginWithMQTTUserInfo:
     @abstrac 用户登陆MQTT服务器
     @discussion 必须登陆以后才可以登陆
     @param userinfo block
     */
    - (void)loginWithMQTTUserInfo:(MQTTUserInfo *)userinfo complete:(BOOL(^)(MQTTConnectionCode code, NSString *msg))block;
    
    /**
     @method addSubscriptionWithTheme:
     @abstrac 订阅主题
     @discussion 默认为@"$SYS/IM"
     @param theme NSString *
     */
    - (BOOL)addSubscriptionWithTheme:(NSString *)theme;
    
    /**
     @method disConnection
     @abstrac 中断链接
     */
    - (void)disConnection;
    
    /**
     @method sendMessageWithData:
     @abstrac 发送消息
     @param data NSString
     */
    - (void)sendMessageWithData:(NSData *)data;
    
    /**
     @method isSendWithMessageBody:
     @abstrac 判断是不是发送者
     @discussion 传入一个消息对象
     @param body MqttMessageBody*
     @result BOOL (NO 接收者/YES 发送者)
     */
    - (BOOL)isSendWithMessageBody:(MqttMessageBody *)body;
    
    
    /**
     @method addDelegatesWithObject:
     @abstrac 添加一个代理对象
     @discussion 传入一个代理对象
     @param delegate id<AVAMqttManagerDelegate> 代理对象
     */
    - (void)addDelegatesWithObject:(id<AVAMqttManagerDelegate>)delegate;
    
    /**
     @method removeDelegateObject:
     @abstrac 删除一个代理对象
     @discussion 传入一个代理对象
     @param delegate id<AVAMqttManagerDelegate> 代理对象
     */
    - (void)removeDelegateObject:(id<AVAMqttManagerDelegate>)delegate;
    
    @end
    
    
    /** 登陆方法
     *   - (void)loginWithMQTTUserInfo:(MQTTUserInfo *)userinfo
     *  complete:(BOOL(^)(MQTTConnectionCode code, NSString *msg))block;
     */
    
    在使用MQTTClient:

    1.需要创建一个MQTTSession对象,这是管理链接的上下文,控制链接,中断,发送,消息,订阅和验证等等。
    MQTTSession是MQTTClient的core类的上层封装,相当于一个外部接口类,作者给其定义了多种方法。

    2.设置一个MQTTSession的Delegate,用来处理链接相关的回调。

    3.定义自己的通讯格式,上一章举例了一个MessageBody对象(正常开发需要更多字段去标识一条消息)

    注意

    1.MQTTSession提供了两类型的构建方法
    a.常规方法

    + (id)alloc;
    - (id)init;
    

    b.类别中添加的方法

    - (MQTTSession *)initWithClientId:(NSString *)clientId
                             userName:(NSString *)userName
                             password:(NSString *)password
                            keepAlive:(UInt16)keepAliveInterval
                       connectMessage:(MQTTMessage *)theConnectMessage
                         cleanSession:(BOOL)cleanSessionFlag
                                 will:(BOOL)willFlag
                            willTopic:(NSString *)willTopic
                              willMsg:(NSData *)willMsg
                              willQoS:(MQTTQosLevel)willQoS
                       willRetainFlag:(BOOL)willRetainFlag
                        protocolLevel:(UInt8)protocolLevel
                                queue:(dispatch_queue_t)queue
                       securityPolicy:(MQTTSSLSecurityPolicy *) securityPolicy
                         certificates:(NSArray *)certificates;
    

    虽然作者很贴心对参数进行了解释,但我还是要在说一下,避免篇幅过短成了水文

    ClientId:客户机标识符向服务器标识客户机。如果为零,则生成随机的clientID
    
    userName:用于身份验证的用户名(或ID)的nsstring对象。可能是零。
    
    password:用户密码的nsstring对象。如果用户名为零,密码也必须为零。
    
    keepAlive:是以秒为单位的时间间隔。mqttclient确保发送的控制包之间的间隔不超过keep-alive值。在没有发送任何其他控制包的情况下,客户机发送一个pingreq包,设置心跳间隔不得大于120s
    
    connectMessage:链接发送的消息
    
    cleanSession:指定服务器是否应放弃以前的会话信息。
    
    will:will标志设置为yes,则表示当服务器检测到客户机由于任何原因(而非客户机主动断开数据包)断开连接时,服务器必须发布will消息。异常退出
    
    willTopic:如果上一项will标志设置为yes,will主题是一个字符串,否则为nil。
    
    willMsg:如果will标志设置为yes,则必须指定will消息,否则为nil。
    
    willQoS:指定发布will消息时要使用的qos级别。如果will标志设置为no,那么will qos必须设置为0。
    
    willRetainFlag:指示服务器是否应使用retainFlag发布will消息。如果will标志设置为no,则will retain标志必须设置为no。如果will标志设置为yes:如果will retain设置为no,服务器必须将will消息发布为非保留发布[mqtt-3.1.2-14]。如果will retain设置为yes,服务器必须将will消息发布为保留发布[mqtt-3.1.2-15]。
         
    protocolLevel:指定要使用的协议。协议版本3.1.1的协议级别字段的值为4。版本3.1的值为3。
         
    queue:安排流的队列进行排队
    
    securityPolicy:安全策略用于评估安全连接的服务器信任的安全策略。
    
    certificates:提供的描述回复需要客户端证书的服务器的身份证书。
    

    我采用的创建方式

    // MQTT配置类,设置访问地址和端口号
    // MQTTCFSocketTransport 安全验证管理
    MQTTCFSocketTransport *transport = [[MQTTCFSocketTransport alloc] init];
    transport.host = HOST;
    transport.port = PORT;
    
    self.session = [[MQTTSession alloc] init];
    self.session.transport = transport;
    self.session.delegate = self;    
    
    // 设置超时
    [self.session setDupTimeout:30];
    // 设置账号密码
    [self.session setUserName:userinfo.username];
    [self.session setPassword:userinfo.password];
    [self.session subscribeToTopic:DefaultsTheme atLevel:MQTTQosLevelAtMostOnce];
    
    验证管理
    - (MQTTSSLSecurityPolicy *)customSecurityPolicy {
        
        MQTTSSLSecurityPolicy *securityPolicy = [MQTTSSLSecurityPolicy policyWithPinningMode:MQTTSSLPinningModeNone];
        
        // 是否使用验证
        securityPolicy.allowInvalidCertificates = YES;
        securityPolicy.validatesCertificateChain = YES;
        securityPolicy.validatesDomainName = NO;
        // 需要证书请设置这个
        // securityPolicy.pinnedCertificates
        return securityPolicy;
    }
    
    如何查看状态

    这里MQTTClient很贴心为我们提供了很多回调,包括链接状态的回调

    /** for mqttio-OBJC backward compatibility
     @param session the MQTTSession reporting the event
     @param eventCode the code of the event
     */
    - (void)session:(MQTTSession*)session handleEvent:(MQTTSessionEvent)eventCode;
    
    /** gets called when a connection has been successfully established
     @param session the MQTTSession reporting the connect
     
     */
    - (void)connected:(MQTTSession *)session;
    
    /** gets called when a connection has been successfully established
     @param session the MQTTSession reporting the connect
     @param sessionPresent represents the Session Present flag sent by the broker
     
     */
    - (void)connected:(MQTTSession *)session sessionPresent:(BOOL)sessionPresent;
    
    /** gets called when a connection has been refused
     @param session the MQTTSession reporting the refusal
     @param error an optional additional error object with additional information
     */
    - (void)connectionRefused:(MQTTSession *)session error:(NSError *)error;
    
    /** gets called when a connection has been closed
     @param session the MQTTSession reporting the close
    
     */
    - (void)connectionClosed:(MQTTSession *)session;
    
    /** gets called when a connection error happened
     @param session the MQTTSession reporting the connect error
     @param error an optional additional error object with additional information
     */
    - (void)connectionError:(MQTTSession *)session error:(NSError *)error;
    
    

    这里为了快速用了KVC,去观察了“status”属性

    // 添加监听状态观察者
    [self.session addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:nil];
    
    // 监听当前连接状态
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
        MQTTSessionStatus eventCode = self.session.status;
        switch (eventCode) {
            case MQTTSessionStatusCreated:
                NSLog(@"%s\n创建链接:%ld", __func__, (long)eventCode);
                break;
            case MQTTSessionStatusConnecting:
                NSLog(@"%s\n链接中:%ld", __func__, (long)eventCode);
                break;
            case MQTTSessionStatusConnected:
                NSLog(@"%s\n已经链接:%ld", __func__, (long)eventCode);
                if (_interruptblock) {
                    self.interruptblock(MQTTConnectionCodeDidConnection, @"已经链接了");
                }
                break;
            case MQTTSessionStatusDisconnecting:
                NSLog(@"%s\n正在断开链接:%ld", __func__, (long)eventCode);
                break;
            case MQTTSessionStatusClosed:
                NSLog(@"%s\n关闭链接:%ld", __func__, (long)eventCode);
                if (self.isClose) {
                    return;
                } else {
                    [self.session connect];
                }
            default:
                NSLog(@"%s\n链接错误:%ld", __func__, (long)eventCode);
                break;
        }
    }
    

    Demo路径:https://github.com/Avanlanching/MQTTDemo

    相关文章

      网友评论

        本文标题:iOS mqtt & protobuf(三) 合体

        本文链接:https://www.haomeiwen.com/subject/lhajbqtx.html