有一段代码使用 CFHostStartInfoResolution() 进行 DNS 查找。然而,这是同步的,因此会在返回之前阻止任何内容 - 这很糟糕,而且我还认为,当连接较弱时,它会因超时而导致崩溃(当连接不好时,它会直接安全地失败)
所以我想异步执行此操作,正如文档 https://developer.apple.com/library/ios/documentation/CoreFoundation/Reference/CFHostRef/Reference/reference.html 中应该的那样 新文档 URL 20190227:https://developer.apple.com/documentation/cfnetwork/cfhostref
具体来说:
If you want to resolve the host asynchronously. call CFHostSetClient to associate your client context and user-defined callback function with the host. Then call CFHostScheduleWithRunLoop to schedule the host on a run loop.
然而,这让我望而却步,因为我已经很久没有编写 C 代码了,无法正确获得回调和运行循环/线程。
我应该如何调用CFHostSetClient、CFHostScheduleWithRunLoop,以及如何实现这些回调?我需要开始一个新线程吗?
最佳答案
实际上 CFHost
从 macOS 10.7 开始就有一个错误。在 10.7 之前,可以在第二个线程上调用 CFHostCancelInfoResolution()
来取消同步查找,但从 10.7 开始,这不再可能了(它只是不会取消查找)。我在 2013 年向 Apple 报告了这一问题(错误编号为 13672880),但尽管已确认,但 Apple 至今仍未修复该问题。
然而更有趣的部分是苹果在回复中的建议:
The best API for host name resolution is DNSServiceGetAddrInfo and that's asynchronous and cancelable.
据记载,该 API 自 10.11.4 起就存在于 macOS 上,自 9.3 以来存在于 iOS 上,自 9.2 以来存在于 tvOS 上,自 2.2 以来存在于 watchOS 上 - 但我认为这不可能是正确的,它一定已经存在,否则苹果怎么会推荐它2013 年(2015 年发布 10.11)。我可以确认这个 API 也存在于 iOS 8 和 macOS 10.9 上,甚至可能更早地存在于这两个系统上。
此 API 在内部使用同步 C 调用 getaddrinfo()
的未记录的异步版本,当今所有 POSIX 类系统上都可以找到该调用。
与其他 API 相比的一个优点是,您可以选择是否只想检索 IPv4、IPv6 或两种类型的地址,也可以让系统决定为您选择地址系列,具体取决于系统考虑的地址目前可达(这是大多数其他解析 API 的默认设置)。
此外,如果系统具有多个事件网络接口(interface)(例如电缆 + WiFi 或 WiFi + 移动),您可以选择要使用的接口(interface),因为不同的接口(interface)上可能设置不同的 DNS 设置(并且不同的 DNS 服务器可以提供不同的结果)对于相同的域名)。如果您不选择其中之一,系统将始终使用当前的默认服务器(这是大多数其他解析 API 的默认服务器)。
关于ios - 异步 DNS 查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18529436/