Ios DNS异步查找

Ios DNS异步查找,ios,multithreading,asynchronous,dns,Ios,Multithreading,Asynchronous,Dns,有一段代码使用CFHostStartInfoResolution()进行DNS查找。然而,这是同步的,因此在它返回之前会阻止任何东西-这是坏的,我还认为它会在连接弱时由于超时而导致崩溃(当它坏时,它会直接安全地失败) 所以我想异步地做这件事,就像在文档中应该做的那样 新文档URL 20190227: 具体来说,它说: 如果要异步解析主机。调用CFHostSetClient 将客户端上下文与用户定义的回调函数关联 和主人在一起。然后调用CFHostScheduleWithRunLoop来调度 运行

有一段代码使用CFHostStartInfoResolution()进行DNS查找。然而,这是同步的,因此在它返回之前会阻止任何东西-这是坏的,我还认为它会在连接弱时由于超时而导致崩溃(当它坏时,它会直接安全地失败)

所以我想异步地做这件事,就像在文档中应该做的那样 新文档URL 20190227

具体来说,它说:

如果要异步解析主机。调用CFHostSetClient 将客户端上下文与用户定义的回调函数关联 和主人在一起。然后调用CFHostScheduleWithRunLoop来调度 运行循环上的主机

然而,这让我很反感,因为我已经很久没有编写C代码了,无法正确地获得回调和运行循环/线程


我应该如何调用CFHostSetClient、CFHostScheduleWithRunLoop,以及如何实现这些回调?我需要开始一个新的线程吗?

应该是这样的

CFHostSetClient(host, callbackFunction, hostContext);
CFHostScheduleWithRunLoop(host, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
CFHostStartInfoResolution(host, kCFHostAddresses, 0);
和调用函数

void callbackFunction(CFHostRef theHost, CFHostInfoType typeInfo, const CFStreamError *error, void *info) {
    // Do something
}

您不需要启动新线程,系统将为您执行。

实际上
CFHost
从10.7开始在macOS上就有一个bug。在10.7之前,可以在第二个线程上取消调用
cfhostcancelinformalesolution()
的同步查找,但从10.7开始,这就不再可能了(它只是不会取消查找)。我在2013年向苹果公司报告了这一情况(错误号为13672880),但尽管得到了证实,苹果公司至今仍未修复

然而更有趣的是苹果在他们的回复中提出的建议:

主机名解析的最佳API是DNSServiceGetAddrInfo 这是异步的和可取消的

据文件记载,该API自10.11.4开始出现在macOS上,自9.3开始出现在iOS上,自9.2开始出现在tvOS上,自2.2开始出现在watchOS上——但我认为这不可能是正确的,它必须已经存在,否则苹果将如何在2013年推荐它(10.11于2015年发布)。我可以确认这个API也存在于iOS 8和macOS 10.9上,甚至可能更早地存在于这两个系统上

此API在内部使用未记录的异步版本的同步C调用
getaddrinfo()
,目前在所有类似POSIX的系统上都可以找到该调用

与其他API相比的一个优势是,您可以选择是否只检索IPv4、IPv6或这两种地址,或者让系统决定为您选择地址系列,具体取决于系统认为当前可访问的地址(这是大多数其他解析API的默认设置)


此外,如果系统具有多个活动网络接口(例如,电缆+WiFi或WiFi+移动),您可以选择要使用的接口,因为不同的接口上可能会设置不同的DNS设置(并且不同的DNS服务器可以为同一域名提供不同的结果)。如果您不选择一个,系统将始终使用当前默认服务器(这是大多数其他解析API的默认服务器)。

这让我找到了正确的方向:好的,谢谢,我让它工作了。我想。。。我可以在hostContext中将调用者作为参数传递,这样我就可以在完成时从callbackFunction回调到流。类似这样的内容:
CFHostClientContext CFHostClientContext;cfhostclientcontext.version=0;cfhostclientcontext.retain=nil;cfhostclientcontext.release=nil;cfhostclientcontext.copyDescription=nil;cfhostclientcontext.info=self
CFHostSetClient(主机、callbackFunction和cfhostclientcontext)
然后在callback函数中将
info
转换为
self
的类型。谢谢@Jonny