前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)

iOS进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)

作者头像
公众号iOS逆向
发布2021-08-25 17:10:09
1.8K0
发布2021-08-25 17:10:09
举报
文章被收录于专栏:iOS逆向与安全iOS逆向与安全

前言

进程通信方案会有以下几种(根据具体场景进行选择)

1:Universal Links、URL Scheme 常用的App间传值方式,常见于分享和app间跳转。

https://kunnan.blog.csdn.net/article/details/119773640 iOS 创建 Universal Links

2:Keychain 借助系统类 KeychainItemWrapper来使用。常见于免登陆 (同公司产品间)

3:UIPasteboard 粘贴板。 淘宝的链接分享。

4:UIDocumentInteractionController 常用于文件的分享

5:local socket(本文内容)

如果你对IPC不了解,可以先看下这篇文章:Inter process Communication

https://blog.csdn.net/z929118967/article/details/77981259 iOS【 ASO项目使用的技术】之 Inter process Communication

登录 iTunes Store 这个输入框的弹出流程是由itunesstored 控制,process:SpringBoard 进行处理,采用SBUserNotificationAlert的方式进行进程间的消息传递。

I 、方案案例:local socket

采用Local Socket方案(TCP)创建服务端和客户端从而达到通讯效果。

  • 基于GCDAsyncSocket提供的解决方案

基于 CFSocket、GCD 进行的封装,支持 TCP 和 UDP

代码语言:javascript
复制

platform :ios, '8.0'
inhibit_all_warnings!

#use_frameworks!
target 'localScoket' do
   pod 'CocoaAsyncSocket'
end

target 'localScoket4client' do
   pod 'CocoaAsyncSocket'
end

1.1 基础知识:Socket 通讯过程

  • CFSocket(纯 C)

苹果对对底层 BSD Socket 进行轻量级的封装。API:CFSocekt 用于建立连接,CFStream 用于读写数据。

  • tcp
  • UDP
  • TCP 的三次握手建立连接
  • TCP 的四次挥手释放连接
  • 先挥手再握手(先断开再连接)

公众号:iOS逆向

  • 先握手再挥手(先连接再断开)

公众号:iOS逆向

1.2 serverSocket

代码语言:javascript
复制
#import <GCDAsyncSocket.h>

@interface ViewController ()

{
    GCDAsyncSocket *_serverSocket;
}

@property(strong,nonatomic)NSMutableArray *clientSocket;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    _clientSocket = [NSMutableArray array];
    
    
    //创建服务端的socket,注意这里的是初始化的同时已经指定了delegate
    _serverSocket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    
    
    [self startChatServer];
    
    
}



-(void)startChatServer{
    //打开监听端口
    NSError *err;
    [_serverSocket acceptOnPort:12345 error:&err];
    if (!err) {
        NSLog(@"Server 服务开启成功");
    }else{
        NSLog(@"Server 服务开启失败");
    }
}
#pragma mark 有客户端建立连接的时候调用
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
    //sock为服务端的socket,服务端的socket只负责客户端的连接,不负责数据的读取。   newSocket为客户端的socket    NSLog(@"服务端的socket %p 客户端的socket %p",sock,newSocket);
    //保存客户端的socket,如果不保存,服务器会自动断开与客户端的连接(客户端那边会报断开连接的log)
    NSLog(@"Server %s",__func__);
    [self.clientSocket addObject:newSocket];
    
    //newSocket为客户端的Socket。这里读取数据
    [newSocket readDataWithTimeout:-1 tag:100];
}
#pragma mark 服务器写数据给客户端
-(void)socket:(GCDAsyncSocket *)sock didWriteDataWithTag:(long)tag{
    NSLog(@"Server %s",__func__);
    [sock readDataWithTimeout:-1 tag:100];
}

#pragma mark 接收客户端传递过来的数据
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
    //sock为客户端的socket
    NSLog(@"Server 客户端的socket %p",sock);
    //接收到数据
    NSString *receiverStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    NSLog(@"Server receiverStr :%@",receiverStr);
    // 把回车和换行字符去掉,接收到的字符串有时候包括这2个,导致判断quit指令的时候判断不相等
    receiverStr = [receiverStr stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    receiverStr = [receiverStr stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    
    //判断是登录指令还是发送聊天数据的指令。这些指令都是自定义的
    //登录指令
    if([receiverStr hasPrefix:@"iam:"]){        // 获取用户名
        NSString *user = [receiverStr componentsSeparatedByString:@":"][1];
        // 响应给客户端的数据
        NSString *respStr = [user stringByAppendingString:@"has joined"];
        [sock writeData:[respStr dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    }
    //聊天指令
    if ([receiverStr hasPrefix:@"msg:"]) {
        //截取聊天消息
        NSString *msg = [receiverStr componentsSeparatedByString:@":"][1];
        [sock writeData:[msg dataUsingEncoding:NSUTF8StringEncoding] withTimeout:-1 tag:0];
    }
    //quit指令
    if ([receiverStr isEqualToString:@"quit"]) {
        //断开连接
        [sock disconnect];
        //移除socket
        [self.clientSocket removeObject:sock];
    }
    NSLog(@"Server %s",__func__);
}




公众号:iOS逆向

1.3 clientSocket

公众号:iOS逆向

这部分代码请看CSDN原文,或者下载demo

1.4 完整demo

  • 从CSDN下载demo https://download.csdn.net/download/u011018979/15137188

see also

  • tweak 项目 快速搭建CocoaAsyncSocket(建连、断开、重连、心跳、通用请求)

https://kunnan.blog.csdn.net/article/details/77053764

文章作者

文章标题

文章链接

公众号:iOS逆向

进程间的实时通讯

https://kunnan.blog.csdn.net/article/details/109616038

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-08-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 iOS逆向 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • I 、方案案例:local socket
    • 1.1 基础知识:Socket 通讯过程
      • 1.2 serverSocket
        • 1.3 clientSocket
          • 1.4 完整demo
          • see also
          相关产品与服务
          文件存储
          文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档