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

相關文章
相關標籤/搜索