我打電話DNSServiceBrowse
,具有「共享連接」(見dns_sd.h
對於文件)如:
DNSServiceCreateConnection(&ServiceRef);
// Need to copy the main ref to another variable.
DNSServiceRef BrowseServiceRef = ServiceRef;
DNSServiceBrowse(&BrowseServiceRef, // Receives reference to Bonjour browser object.
kDNSServiceFlagsShareConnection, // Indicate it's a shared connection.
kDNSServiceInterfaceIndexAny, // Browse on all network interfaces.
"_servicename._tcp", // Browse for service types.
NULL, // Browse on the default domain (e.g. local.).
BrowserCallBack, // Callback function when Bonjour events occur.
this); // Callback context.
這是稱爲ServiceDiscovery
一個線程類的主run
方法內。 ServiceRef
是ServiceDiscovery
的成員。
於是馬上按照上面的代碼中,我有一個主事件循環如下所示:
while (true)
{
err = DNSServiceProcessResult(ServiceRef);
if (err != kDNSServiceErr_NoError)
{
DNSServiceRefDeallocate(BrowseServiceRef);
DNSServiceRefDeallocate(ServiceRef);
ServiceRef = nullptr;
}
}
然後,在BrowserCallback
你必須設置決心要求:
void DNSSD_API ServiceDiscovery::BrowserCallBack(DNSServiceRef inServiceRef,
DNSServiceFlags inFlags,
uint32_t inIFI,
DNSServiceErrorType inError,
const char* inName,
const char* inType,
const char* inDomain,
void* inContext)
{
(void) inServiceRef; // Unused
ServiceDiscovery* sd = (ServiceDiscovery*)inContext;
...
// Pass a copy of the main DNSServiceRef (just a pointer). We don't
// hang to the local copy since it's passed in the resolve callback,
// where we deallocate it.
DNSServiceRef resolveServiceRef = sd->ServiceRef;
DNSServiceErrorType err =
DNSServiceResolve(&resolveServiceRef,
kDNSServiceFlagsShareConnection, // Indicate it's a shared connection.
inIFI,
inName,
inType,
inDomain,
ResolveCallBack,
sd);
然後在ResolveCallback
你應該擁有你需要的一切。
// Callback for Bonjour resolve events.
void DNSSD_API ServiceDiscovery::ResolveCallBack(DNSServiceRef inServiceRef,
DNSServiceFlags inFlags,
uint32_t inIFI,
DNSServiceErrorType inError,
const char* fullname,
const char* hosttarget,
uint16_t port, /* In network byte order */
uint16_t txtLen,
const unsigned char* txtRecord,
void* inContext)
{
ServiceDiscovery* sd = (ServiceDiscovery*)inContext;
assert(sd);
// Save off the connection info, get TXT records, etc.
...
// Deallocate the DNSServiceRef.
DNSServiceRefDeallocate(inServiceRef);
}
hosttarget
和port
包含您的連接信息,並且可以使用DNS-SD API(例如TXTRecordGetCount
和TXTRecordGetItemAtIndex
)獲得的任何文字記錄。
使用共享連接引用時,必須在完成每個引用時基於(或從中複製父引用)來釋放每個引用。當您將共享引用的副本傳遞給其中一個函數時,我認爲DNS-SD API會執行一些引用計數(以及父/子關係)。再次請參閱文檔以獲取詳細信息。
我嘗試不使用共享連接,我只是傳遞ServiceRef
,導致它被覆蓋在回調和我的主循環中,以混淆。我想如果你不使用共享連接,你需要維護一個需要進一步處理的引用列表(並且處理每個引用),然後在完成時將它們銷燬。共享連接方式似乎更容易。