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

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: iOS进程间的实时通讯方案: local socket(解决扩展和容器应用的实时通讯问题)

前言

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

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

image.png

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

I 、方案案例:local socket

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

  • 基于GCDAsyncSocket提供的解决方案

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

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

image.png

UDP

image.png

TCP 的三次握手建立连接

image.png

TCP 的四次挥手释放连接

image.png

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

image.png

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

image.png

1.2 serverSocket

#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__);
}

image.png

1.3 clientSocket

image.png

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

1.4  完整demo

see also

目录
相关文章
|
3月前
|
Kubernetes Docker Python
Docker 与 Kubernetes 容器化部署核心技术及企业级应用实践全方案解析
本文详解Docker与Kubernetes容器化技术,涵盖概念原理、环境搭建、镜像构建、应用部署及监控扩展,助你掌握企业级容器化方案,提升应用开发与运维效率。
768 108
|
3月前
|
运维 监控 数据可视化
小白也能部署应用,3个免费的容器化部署工具测评
本文对比了三款容器化部署工具:Docker Compose、Portainer 和 Websoft9。Docker Compose 适合开发者编排多容器应用,Portainer 提供图形化管理界面,而 Websoft9 则面向中小企业和非技术人员,提供一键部署与全流程运维支持,真正实现“开箱即用”。三款工具各有定位,Websoft9 更贴近大众用户需求。
小白也能部署应用,3个免费的容器化部署工具测评
|
1月前
|
监控 Kubernetes 安全
还没搞懂Docker? Docker容器技术实战指南 ! 从入门到企业级应用 !
蒋星熠Jaxonic,技术探索者,以代码为笔,在二进制星河中书写极客诗篇。专注Docker与容器化实践,分享从入门到企业级应用的深度经验,助力开发者乘风破浪,驶向云原生新世界。
还没搞懂Docker? Docker容器技术实战指南 ! 从入门到企业级应用 !
|
4月前
|
存储 监控 Java
如何对迁移到Docker容器中的应用进行性能优化?
如何对迁移到Docker容器中的应用进行性能优化?
342 59
|
4月前
|
缓存 Java Docker
如何对应用代码进行优化以提高在Docker容器中的性能?
如何对应用代码进行优化以提高在Docker容器中的性能?
285 1
|
5月前
|
数据可视化 API UED
126. [HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 进阶篇
在基础篇中,我们已经实现了电商应用商品筛选侧边栏的基本布局和功能。在本篇教程中,我们将深入探讨如何通过状态管理和数据绑定,实现更加复杂的交互功能,提升用户体验。
100 2
126. [HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 进阶篇
|
5月前
|
UED 容器
125.[HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 基础篇
在现代电商应用中,商品筛选功能是提升用户购物体验的关键元素。HarmonyOS NEXT提供的`SideBarContainer`组件非常适合实现这类功能,它可以创建一个可显示和隐藏的侧边栏,用于放置各种筛选条件,帮助用户快速找到心仪的商品。
147 1
125.[HarmonyOS NEXT 实战案例二:SideBarContainer] 侧边栏容器实战:电商应用商品筛选侧边栏 基础篇
|
8月前
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。
|
8月前
|
Linux Shell
Linux 进程前台后台切换与作业控制
进程前台/后台切换及作业控制简介: 在 Shell 中,启动的程序默认为前台进程,会占用终端直到执行完毕。例如,执行 `./shella.sh` 时,终端会被占用。为避免不便,可将命令放到后台运行,如 `./shella.sh &`,此时终端命令行立即返回,可继续输入其他命令。 常用作业控制命令: - `fg %1`:将后台作业切换到前台。 - `Ctrl + Z`:暂停前台作业并放到后台。 - `bg %1`:让暂停的后台作业继续执行。 - `kill %1`:终止后台作业。 优先级调整:
614 5
|
运维 关系型数据库 MySQL
掌握taskset:优化你的Linux进程,提升系统性能
在多核处理器成为现代计算标准的今天,运维人员和性能调优人员面临着如何有效利用这些处理能力的挑战。优化进程运行的位置不仅可以提高性能,还能更好地管理和分配系统资源。 其中,taskset命令是一个强大的工具,它允许管理员将进程绑定到特定的CPU核心,减少上下文切换的开销,从而提升整体效率。
掌握taskset:优化你的Linux进程,提升系统性能