iOS小技能: tweak 整合CocoaAsyncSocket(建連、斷開、重連、心跳、通用請求)

語言: CN / TW / HK

持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第26天,點選檢視活動詳情

前言

  1. 應用場景:app端整合CocoaAsyncSocket與服務端進行通訊,利用實現機器人功能。
  2. 即時通訊的大資料處理邏輯:多執行緒逐條處理,你也可以採用事務處理聊天記錄大資料,但如果發生錯誤需要全部回滾。

    建立NSBlockOperation 放到NSOperationQueue非同步執行。

    系統會自動將NSOperationQueue中的NSOperation取出,將取出的NSOperation封裝的操作放到一個新的執行緒中執行。

  3. 注意事項:socket不推薦放在主佇列

```objectivec [[GCDAsyncSocket alloc] initWithDelegate:delegate delegateQueue:dispatch_get_main_queue()];

``` 推薦自定義一個序列佇列。

I 知識儲備

1.1 tweak是什麼?

tweak的實質就是ios平臺的動態庫。IOS平臺上有兩種形勢的動態庫,dylib與framework。Framework這種開發者用的比較多,而dylib這種就相對比較少一點,比如libsqlite.dylib,libz.dylib等。而tweak用的正是dylib這種形勢的動態庫。

越獄開發中,各種破解補丁的統稱為Tweak。iOS tweak 基本上都依賴於cydia Substrate的動態庫, Substrate是Cydia 作者Jay Freeman 的作品,它的主要功能是hook某個App修改程式碼,比如替換其中方法的實現;Cydia上的tweak都是基於Mobile Substrate實現的。 ```bash iPhone:~ root# cd /Library/MobileSubstrate/DynamicLibraries

```

我們可以在裝置的/Library/MobileSubstrate/DynamicLibraries目錄下檢視手機上存在著的所有tweak。這個目錄下除dylib外還存在著plist與bundle兩種格式的檔案,plist檔案是用來標識該tweak的作用範圍,而bundle是tweak所用到的資原始檔。

those的安裝

http://blog.csdn.net/z929118967/article/details/77051246

1.2 長連線

  • http請求:

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

  • 長連線

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

  • 短連線,並行連線,持久連線與長連線

    http://blog.csdn.net/z929118967/article/details/86494386

II 採用MonkeyDev 的logos Tweak模版 整合CocoaAsyncSocket

因為它支援使用CocoaPods,可採用Node.js搭建對應的服務端。

2.1 讀訊息的設定

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

```objectivec - (void)socketWriteData:(NSString *)data { // 開始寫資料 NSLog(@"socketWriteData:%@",data);

NSData *requestData = [data dataUsingEncoding:NSUTF8StringEncoding];
[self.socket writeData:requestData withTimeout:-1 tag:0];

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

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

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

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

} ``` - 開始讀資料

```objectivec /* 開始讀資料 /

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

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

2.2 業務邏輯的處理

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

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

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

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

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

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

處理服務端的訊息推送 ```objectivec

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];// 修改為連線建立之後  就立馬監聽

```

2.5 異常斷開連線處理

  • 失敗重新連線

```objectivec

pragma mark - ** 失敗重新連線

  • (void)socketDidDisconnect:(GCDAsyncSocket )socket withError:(NSError )err { ```
  • 連線失敗的判斷

```objectivec - (void)socketWriteDataWithRequestType:(GACRequestType)type requestBody:(nonnull NSDictionary *)body completion:(nullable SocketDidReadBlock)callback { NSLog(@"socketWriteData:%@",body); if (self.socketManager.connectStatus == -1) { NSLog(@"socket 未連通");

```

  • 連線成功的處理 ```objectivec
  • (void)socket:(GCDAsyncSocket )socket didConnectToHost:(NSString )host port:(UInt16)port {

    self.socketManager.connectStatus = 1;//此處的狀態設定,提前到建立連線的地方 //此時將重連的時鐘刪除 [self.socketManager invalidatereconnectTimer]; ```

2.6 常見問題

問題:

```bash 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

2.7 demo下載

```bash

pragma mark - ** CMessageMgr init

  • (CMessageMgr *)init

{ %log(); CMessageMgr *ret = %orig; globalMessageMgr =ret;

id fromUser = [%c(SettingUtil) getLocalUsrName:0];//如果微信沒有登入的話,就獲取不到
if ( fromUser == nil/* condition */)
{
    return ret ;
    /* code */
}

CContactMgr *contactMgr = [[objc_getClass("MMServiceCenter") defaultCenter] getService:objc_getClass("CContactMgr")];
CContact *selfContact = [contactMgr getSelfContact];

//NSLog(@" selfContact :%@", selfContact);//MMSessionInfo

/**
 建立長連線的時候,可以根據host的不同可以精準的推送對應的長連線
 */

_connectConfig = [[GACConnectConfig alloc] init];
_connectConfig.channels = @"dkf";
_connectConfig.currentChannel = @"dkf";
_connectConfig.host = KconnectConfighost;
_connectConfig.port = [KconnectConfigport intValue];
_connectConfig.socketVersion = 5;
// 為當前登入的微信ID
_connectConfig.WeChatNum = fromUser;
_connectConfig.token = @"f14c431d1a6efa9";
_connectConfig.selfContact =selfContact;
// 1.自定義配置連線環境
[[GCDAsyncSocketCommunicationManager sharedInstance] createSocketWithConfig:_connectConfig];

// 註冊通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setupRESPONSE_TYPE:) name:kRESPONSE_TYPENotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setupRESPONSE_TYPENOTIFY:) name:kRESPONSE_TYPERESPONSE_TYPE_NOTIFYNotification object:nil];

//

return ret;

}

```

  • 處理訊息提送任務 在這裡插入圖片描述

依賴的第三方庫:CocoaAsyncSocket ```objectivec 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 ```

see also

更多內容請關注 #公號:iOS逆向,只為你呈現有價值的資訊,專注於移動端技術研究領域;