如何彻底停止并清理nw_connection_create创建的TCP连接?
使用Apple Network.Framework的TCP连接清理问题
我正在使用Apple的Network.Framework,通过nw_connection_create()创建TCP连接(这是现代且未被弃用的TCP连接创建方式)。
当前实现流程
- 调用
nw_endpoint_create_host()创建端点 - 调用
nw_connection_create()创建连接 - 创建串行调度队列:
dispatch_queue_create(DISPATCH_QUEUE_SERIAL) - 通过
nw_connection_set_queue()为连接分配队列 - 设置状态回调:
nw_connection_set_state_changed_handler() - 启动连接:
nw_connection_start - 发起首次接收请求(先递增原子变量
RecvCallCount):nw_connection_receive
目前能正常发送、接收数据及获取连接状态。每次接收回调触发时会递减RecvCallCount,以此确认当前没有等待中的回调。
关闭连接时的问题
关闭套接字的操作流程:
- 调用
nw_connection_force_cancel() - 将connection置为nil或释放
- 将调度队列置为nil或释放
- 持有连接的类被析构
执行上述操作后,会收到来自接收回调或状态变更处理器的虚假回调,这些回调会访问已析构的对象,最终导致崩溃。根据Xcode的信息,这些回调似乎来自非主线程。
已尝试的解决方法
- 对连接句柄的操作加互斥锁,避免在
nw_connection_force_cancel()后调用send或recv导致崩溃(或已将连接置空) - 开启/关闭ARC(在对应位置手动调用retain/release),问题依旧存在
- 在iOS和macOS平台上测试,问题表现一致
我推测nw_connection_receive是调用与响应一一对应的,因此尝试为每次recv调用设置原子引用计数器,并在析构函数中等待计数器归0。这种方式在一段时间内有效,但偶尔会出现接收回调从未触发的情况,导致无法完成清理。
疑问与求助
是否应该:
- 等待收到
cancel状态更新后再释放资源? - 使用其他方式停止
nw_connection_t? - 刷新调度队列?(已尝试向队列中添加任务,任务能正常执行完成,因此认为析构时队列无等待任务)
- 刷新连接?(未找到可行的实现方法)
正确的套接字终止方式是什么?如何确保调度队列及所有接收回调被彻底清理?我找不到使用nw_系列函数进行完整资源清理的可靠示例,可能遗漏了某些关键点。
内容的提问来源于stack exchange,提问作者Soylent Graham
相关产品推荐
相关产品推荐

