【问题标题】:DNS lookup asynchronously异步 DNS 查找
【发布时间】:2013-08-30 09:26:33
【问题描述】:

有一段代码使用 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 代码了,也无法正确地获得回调和运行循环/线程。

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

【问题讨论】:

标签: ios multithreading asynchronous dns


【解决方案1】:

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

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

    应该是这样的

    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
    }
    

    你不需要启动一个新线程,系统会为你做的。

    【讨论】:

    • 好的,谢谢我让它工作了。我想......我可以将调用者作为参数传递给 hostContext,这样我就可以在从 callbackFunction 完成时回调到流程。像这样的东西:CFHostClientContext cfhostclientcontext; cfhostclientcontext.version = 0; cfhostclientcontext.retain = nil; cfhostclientcontext.release = nil; cfhostclientcontext.copyDescription = nil; cfhostclientcontext.info = self;
    • CFHostSetClient(host, callbackFunction, & cfhostclientcontext); 然后将info 转换为self 在回调函数中的类型。谢谢@Jonny
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-09
    • 1970-01-01
    • 2021-06-28
    • 2016-06-06
    • 1970-01-01
    相关资源
    最近更新 更多