iOS小技能: tweak 集成CocoaAsyncSocket(建連、斷開、重連、心跳、通用請求)
持續創作,加速成長!這是我參與「掘金日新計劃 · 10 月更文挑戰」的第26天,點擊查看活動詳情
前言
- 應用場景:app端集成CocoaAsyncSocket與服務端進行通信,利用實現機器人功能。
- 即時通訊的大數據處理邏輯:多線程逐條處理,你也可以採用事務處理聊天記錄大數據,但如果發生錯誤需要全部回滾。
創建NSBlockOperation 放到NSOperationQueue異步執行。
系統會自動將NSOperationQueue中的NSOperation取出,將取出的NSOperation封裝的操作放到一個新的線程中執行。
- 注意事項: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所用到的資源文件。
1.2 長連接
-
http請求:
每次更新數據都要向對應的端口發送一次請求,之後返回數據之後關閉連接
-
長連接
客户端和服務器一直連着,當有數據更新的時候,服務器會直接發給客户端,不需要客户端主動請求。(client 需要監聽流的輸入) ps:在這過程中,為了保證服務端和客户端一直是連接狀態,客户端會定時不間斷的發送心跳數據到服務器,表明還連接着,不然長時間沒有數據更新,會斷開連接,這樣一直有心跳數據的時候,就會保證了連接沒有中斷,至於心跳數據的內容,就是前端後端共同商量的,和請求的數據是單獨的。(通常採用nstimer)
-
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逆向
,只為你呈現有價值的信息,專注於移動端技術研究領域;
- iOS小技能:UITableView的適配 (iOS10/iOS14/iOS16.0)
- iOS小技能:和uni-app、unity的融合方案
- iOS小技能:iOS15崩潰排查技巧(symbolicatecrash符號化分析問題、導出和隱藏符號)
- iOS小技能:【intercept the HTTP/HTTPS requests 】利用NSURLProtocol 攔截請求
- iOS小技能: tweak 集成CocoaAsyncSocket(建連、斷開、重連、心跳、通用請求)
- iOS小技能:iOS13 證件掃描 & 文字識別API
- iOS小技能:集成下拉刷新控件 & 實現無感知上拉加載更多
- iOS小技能:代碼觸發button的點擊事件、快速找到按鈕action方法
- iOS小技能:撥號、發郵件、短信、應用間跳轉
- iOS小技能:鏈式編程在iOS開發中的應用
- iOS小技能:iOS14 讀取用户剪切板數據彈出提示的兼容方案
- iOS小技能:因境外IP無法訪問導致 App 被拒的解決方案
- iOS小技能:RSA簽名、驗籤、加密、解密的原理
- iOS小技能:Xcode14新特性(適配)
- iOS小技能:Socket基礎知識
- iOS小技能:SKU視圖搭建
- iOS小技能: 日曆的使用(案例:兩個時間的比較、獲取最近30天的數據)
- iOS小技能:1. iOS 實現json數據提交 2. 對同一個URL的多次請求進行數據緩存 3. 檢查網絡狀態
- iOS小技能:使用正則表達式對聊天記錄的關鍵詞進行監控
- iOS小技能:去掉/新增導航欄黑邊(iOS13適配)