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适配)