tweak 專案 快速搭建CocoaAsyncSocket(建連、斷開、重連、心跳、通用請求)

kunnan發表於2017-11-07

前言

GitHub

  • http請求:

每次更新資料都要向對應的埠傳送一次請求,之後返回資料之後關閉連線

  • 長連線

客戶端和伺服器一直連著,當有資料更新的時候,伺服器會直接發給客戶端,不需要客戶端主動請求。(client 需要監聽流的輸入)

ps:在這過程中,為了保證服務端和客戶端一直是連線狀態,客戶端會定時不間斷的傳送心跳資料到伺服器,表明還連線著,不然長時間沒有資料更新,會斷開連線,這樣一直有心跳資料的時候,就會保證了連線沒有中斷,至於心跳資料的內容,就是前端後端共同商量的,和請求的資料是單獨的。(通常採用nstimer)

一、tweak 專案整合CocoaAsyncSocket 可採用MonkeyDev 的logos Tweak模版(支援使用CocoaPods)

  • pod
platform :ios, `8.0`
inhibit_all_warnings!

#use_frameworks!
target `wlentrust` do
   pod `CocoaAsyncSocket`
   pod `JSONModel`, `1.1.0`
   pod `AFNetworking`, `3.0.4`
   pod `XMLDictionary`
end

由於tweak本身就是動態庫,因此暫時只支援靜態庫#use_frameworks!

具體的請看MokeyDev 的logos tweak工程使用注意事項

二、問題解決

  • Cannot synthesize weak property in file using manual reference
    counting
/Users/devzkn/code/tweak/wlentrust/wlentrust/src/socket/GCDAsyncSocketManager/Manager/GCDAsyncSocketCommunicationManager.m:41:1: Cannot synthesize weak property in file using manual reference counting
  • 解決方案:修改專案配置為ARC編譯環境
修改app LLVMXX -language-Object-C 支援ARC
Y-Y-Y-NO

三、程式碼實現

參考

讀訊息的設定

預設讀訊息為timeout 可以設定10

- (void)socketWriteData:(NSString *)data {
    // 開始寫資料
    NSLog(@"socketWriteData:%@",data);
    
    NSData *requestData = [data dataUsingEncoding:NSUTF8StringEncoding];
    [self.socket writeData:requestData withTimeout:-1 tag:0];
//    [self socketBeginReadData];// 修改為連線建立之後  就立馬監聽
}

如果想要實時監聽服務端的訊息推送就可以修改,連線一旦建立 就開始讀

- (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port {

        [self.socketManager socketBeginReadData];// 修改為連線建立之後  就立馬監聽

}
/**
 開始讀資料
 */
#pragma mark - ******** 設定讀資料的timeout   連線建立之後就開始監聽讀取資料

- (void)socketBeginReadData {
    NSLog(@"socketBeginReadData");
    [self.socket readDataToData:[GCDAsyncSocket CRLFData] withTimeout:-1 maxLength:0 tag:0];//考慮使用-1
}

業務邏輯的處理

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {

// 根據服務端返回的訊息型別,解析引數,處理任務
}

實現實時監聽服務端的流的方法

一旦接受到資料 就開啟下一次的監聽輸入流
receive data -》socketBeginReadData

區分 服務端主動推送 和服務端響應的方式

可以讓服務端新增響應型別 進行區分,或者app 端進行判斷響應資料是否包含reqId,這個reqId 是隻有app 主動發起的請求響應時才會存在

處理服務端的訊息推送


    GACRESPONSE_TYPE respType = [json[@"respType"] integerValue];
    
    if(respType == RESPONSE_TYPE_NOTIFY){//訊息通知 服務端的主動通知
        
        //直接傳送通知
        //   1、 RESPONSE_TYPE_NOTIFY 處理服務端主動推送的任務
        
        NSMutableDictionary * userInfo = [NSMutableDictionary dictionaryWithObject:json forKey:kRESPONSE_TYPENotificationjsonKey];//respType 傳送json
        [[NSNotificationCenter defaultCenter] postNotificationName:kRESPONSE_TYPERESPONSE_TYPE_NOTIFYNotification object:self userInfo:userInfo];
        
        
    }else{
        //2、執行對應的block
        
        
        
        SocketDidReadBlock didReadBlock = self.requestsMap[requestID];
        
        //    if (errorCode != 0) {
        //
        //        jsonError = [[NSError alloc]initWithDomain:NSURLErrorDomain code:errorCode userInfo:nil];
        //    }
        
        if (didReadBlock) {
            didReadBlock(jsonError, json);
        }
        
        
    }
    [self.socketManager socketBeginReadData];// 修改為連線建立之後  就立馬監聽

異常斷開連線處理


#pragma mark - ******** 失敗重新連線
- (void)socketDidDisconnect:(GCDAsyncSocket *)socket withError:(NSError *)err {
- (void)socketWriteDataWithRequestType:(GACRequestType)type
                           requestBody:(nonnull NSDictionary *)body
                            completion:(nullable SocketDidReadBlock)callback {
    NSLog(@"socketWriteData:%@",body);
    if (self.socketManager.connectStatus == -1) {
        NSLog(@"socket 未連通");
- (void)socket:(GCDAsyncSocket *)socket didConnectToHost:(NSString *)host port:(UInt16)port {
    
    self.socketManager.connectStatus = 1;//此處的狀態設定,提前到建立連線的地方
   //此時將重連的時鐘刪除
    [self.socketManager invalidatereconnectTimer];

服務端的搭建可以採用Node.js

API大全
PHP API

待續

工程師必備技能 – 90分鐘自己開發一個chrome擴充套件

相關文章