2

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

所以我想异步执行此操作,因为它应该在文档https://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFHostRef/Reference/reference.html 新文档 URL 20190227https:// /developer.apple.com/documentation/cfnetwork/cfhostref

具体来说,它说:

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

然而,这让我很反感,因为我已经很久没有编写 C 代码了,也无法正确获得回调和 runloops/threading。

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

4

2 回答 2

2

实际上CFHost自 10.7 以来在 macOS 上存在错误。在 10.7 之前,可以取消在第二个线程上调用的同步查找CFHostCancelInfoResolution(),但从 10.7 开始,这不再可能(它只是不会取消查找)。我在 2013 年向 Apple 报告了该问题(错误编号为 13672880),但尽管得到了确认,但 Apple 至今从未修复它。

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

用于主机名解析的最佳 API 是DNSServiceGetAddrInfo ,它是异步且可取消的。

这个 API 被记录在 macOS 自 10.11.4、iOS 自 9.3、tvOS 自 9.2 和 watchOS 自 2.2 - 但我认为这不可能正确,它一定存在,否则 Apple 如何在 2013 年推荐它( 10.11 于 2015 年发布)。我可以确认这个 API 也存在于 iOS 8 和 macOS 10.9 上,甚至可能更早出现在这两个系统上。

该 API 在内部使用了其他同步 C 调用的未记录异步版本,该版本可在getaddrinfo()当今所有类似 POSIX 的系统上找到。

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

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

于 2019-02-26T18:55:40.920 回答
1

应该是这样的

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
}

您无需启动新线程,系统会为您完成。

于 2013-08-30T10:14:45.320 回答