2013-10-11 75 views
1

我有一個服務器應用程序在局域網上可以通過DNS-SD發現的設備上運行(即Zeroconf/Bonjour /的avahi)。客戶端設備(也在LAN上)連接到此服務器。我無法控制用於連接到我的服務器應用程序的應用程序,但我知道它們可能使用DNS-SD和mDNS來發現並連接到服務器。我如何獲取標識這些客戶端設備的鏈接本地域名​​,只給出它們在C或C++中的IP地址?從IP地址獲取鏈接本地域名​​(例如,使用組播DNS和DNS-SD進行反向DNS查找)

根據RFC 6762 Multicast DNS - Section 4. Reverse Address Mapping
「贊」。本地「,在IPv4和IPv6反向映射域也被定義爲本地鏈路......因爲這個域名下的名稱對應IPv4的鏈路本地。地址,因此本地鏈接是查找與這些名稱有關的信息的最佳位置是合乎邏輯的。「

因此理論上應該可以通過IP地址來查找鏈路本地域名。有誰知道如何?也許我沒有在正確的位置尋找,但在Bonjour文檔中沒有看到針對此的API調用。

回答

1

我最終通過Apple的Bonjour Dev郵件列表得到了這個問題的答案。按照Quinn「愛斯基摩人!」,這裏是你如何能做到這一點:

static void DNSCallback(
    DNSServiceRef      sdRef, 
    DNSServiceFlags      flags, 
    uint32_t       interfaceIndex, 
    DNSServiceErrorType     errorCode, 
    const char       *fullname, 
    uint16_t       rrtype, 
    uint16_t       rrclass, 
    uint16_t       rdlen, 
    const void       *rdata, 
    uint32_t       ttl, 
    void        *context 
) 
{ 
    const uint8_t *  cursor; 

    fprintf(stderr, "DNSCallback\n"); 
    assert(rrtype == kDNSServiceType_PTR); 
    assert(rrclass == kDNSServiceClass_IN); 
    cursor = (const uint8_t *) rdata; 
    while (*cursor != 0) { 
     fprintf(stderr, "%.*s.", (int) *cursor, cursor + 1); 
     cursor += *cursor + 1; 
    } 
    fprintf(stderr, "\n"); 
} 

static void SocketCallBack(CFSocketRef s, CFSocketCallBackType type, CFDataRef address, const void *data, void *info) 
{ 
    DNSServiceErrorType err; 

    fprintf(stderr, "SocketCallBack\n"); 

    err = DNSServiceProcessResult(((AppDelegate *) info)->sdRef); 
    fprintf(stderr, "err = %d\n", (int) err); 
} 

- (IBAction)testAction:(id)sender 
{ 
    DNSServiceErrorType err; 
    int     sock; 
    CFSocketRef   cfSock; 

    fprintf(stderr, "-[AppDelegate testAction:]\n"); 

    assert(self->sdRef == NULL); 

    err = DNSServiceQueryRecord(
     &self->sdRef, 
     kDNSServiceFlagsForceMulticast, 
     0, 
     "9.40.0.10.in-addr.arpa.", 
     kDNSServiceType_PTR, 
     kDNSServiceClass_IN, 
     DNSCallback, 
     self 
    ); 
    fprintf(stderr, "err = %d\n", (int) err); 

    sock = DNSServiceRefSockFD(self->sdRef); 
    fprintf(stderr, "sock = %d\n", sock); 

    CFSocketContext context = { 0, self, NULL, NULL, NULL }; 

    cfSock = CFSocketCreateWithNative(NULL, sock, kCFSocketReadCallBack, SocketCallBack, &context); 
    assert(cfSock != NULL); 

    CFRunLoopSourceRef rls; 
    rls = CFSocketCreateRunLoopSource(NULL, cfSock, 0); 
    assert(rls != NULL); 

    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 
} 

這個例子將找到的IP地址10.0.40.9鏈路本地主機名。 IP地址以相反的順序插入。