0

到目前为止,我所拥有的是:

void startQueryIPv4(const char *hostName){
printf("startQueryIPv4");
DNSServiceRef serviceRef;
DNSServiceGetAddrInfo(&serviceRef, kDNSServiceFlagsForceMulticast, 0, kDNSServiceProtocol_IPv4, hostName, queryIPv4Callback, NULL);
DNSServiceProcessResult(serviceRef);
DNSServiceRefDeallocate(serviceRef);
}


static void queryIPv4Callback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, uint32_t ttl, void *context){
printf("queryIPv4Callback");

if (errorCode == kDNSServiceErr_NoError) {

    printf("no error");
    char *theAddress = NULL;

    switch(address->sa_family) {
        case AF_INET: {
            struct sockaddr_in *addr_in = (struct sockaddr_in *)address;
            theAddress = malloc(INET_ADDRSTRLEN);
            inet_ntop(AF_INET, &(addr_in->sin_addr), theAddress, INET_ADDRSTRLEN);
            break;
        }
        case AF_INET6: {
            struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address;
            theAddress = malloc(INET6_ADDRSTRLEN);
            inet_ntop(AF_INET6, &(addr_in6->sin6_addr), theAddress, INET6_ADDRSTRLEN);
            break;
        }
        default:
            break;
    }
    printf("IP address: %s\n", theAddress);
    free(theAddress);

} else {
    printf("%d", errorCode);
}

}

但是永远不会调用回调。在控制台中,我收到此错误:TIC Read Status [9:0x0]: 1:57 ObjectiveC 不是我的能力,但我不得不搞砸它。任何帮助将不胜感激。

4

2 回答 2

0

由于 Objective-C 是 C 的真正超集,并且 Darwin 经认证与 SUS 3 兼容,因此您的 iOS 上的 Objective-C 程序应该能够使用 C 接口到系统的名称解析器:getaddrinfo(). 您可以使用此函数的第三个参数来指定您只需要 IPv4 结果(或仅 IPv6 结果)。

您应该注意的事项:

  • 这当然是一个同步接口;如果你想要异步,那么你需要自己安排。

  • getaddrinfo()分配并返回地址的链表,所以

    • 原则上,您可能需要检查多个

    • 完成后,您需要通过以下方式释放列表freeaddrinfo()

于 2017-11-10T17:12:08.783 回答
0

您没有收到回调的原因是您没有使用调度队列。DNSServiceGetAddrInfo API 是异步的。如果您在 Apple 设备上执行此操作,则需要更多类似的内容:

void startQueryIPv4(const char *hostName) {
  printf("startQueryIPv4");
  DNSServiceRef serviceRef;
  DNSServiceGetAddrInfo(&serviceRef, kDNSServiceFlagsForceMulticast, 0, kDNSServiceProtocol_IPv4, hostName, queryIPv4Callback, NULL);
  main_queue = dispatch_get_main_queue();
  DNSServiceSetDispatchQueue(sdref, main_queue);
  dispatch_main();
}

请注意,dispatch_main() 是 libdispatch 的主事件循环:如果您想做其他事情,则需要将其安排在调度循环中,因为 dispatch_main() 不会返回。

在您的原始代码中,您调用了 DNSServiceRefDeallocate(),但在您想停止查询之前,您不能这样做。如果您在开始查询后立即调用它,它将取消查询。因此,例如,您可以从回调中调用它。

但是,更好的流程是执行长期查询 (kDNSServiceFlagsLongLivedQuery),以便在信息更改时获得更新。当然,您随后需要更改您要连接的主机,因此只有在您的应用程序需要长时间连接时才这样做。

此外,您可能会得到多个答案。如果你这样做了,可能有些答案可以联系起来,而其他答案则不行。因此,您可能希望积累答案并尝试每个答案,而不是在您得到的第一个答案不起作用时放弃。如果有更多数据立即到来,回调将包括 kDNSServiceFlagsMoreComing 标志。每次调用回调时,它都会得到一个答案(或查询以某种方式失败的指示)。

当然,这是一个相当低级的 API。如果你想让你的生活更轻松一点,你应该使用 Network Framework。Network Framework 为您完成了“快乐的眼球”部分——尝试每个响应直到它获得连接,然后返回它获得的连接,取消其他响应。

但是你没有问这个,所以我不会在这里详细说明。

于 2021-10-06T21:06:45.767 回答