該程式庫提供了一個僅標頭的跨平台 mDNS 和 C 語言的 DNS-DS 庫。
https://github.com/mjansson/mdns
該圖書館屬於公共領域;您可以重新分發它和/或修改它,沒有任何限制。
由 Mattias Jansson (@maniccoder) 創建
用於討論的 Discord 伺服器 https://discord.gg/M8BwTQrt6c
該程式庫進行 DNS-SD 發現和服務以及一次性單記錄 mDNS 查詢和回應。函式庫沒有完成記憶體分配,所有使用的緩衝區都必須由呼叫者傳入。可以使用使用者資料不透明指標傳遞用於處理的自訂資料。
mdns.c
測試可執行檔示範了所有功能的使用,包括發現、查詢和服務回應。這裡的文檔故意稀疏,範例程式碼有很好的文檔記錄,並且應該提供所有詳細資訊。
用於 mDNS 通訊的套接字可以由函式庫使用mdns_socket_open_ipv4
或mdns_socket_open_ipv6
打開,也可以透過使用mdns_socket_setup_ipv4
或mdns_socket_setup_ipv6
初始化現有套接字來開啟。套接字開啟/設定函數將使用多播成員身份(包括環回)初始化套接字並設定為非阻塞模式。
呼叫mdns_socket_close
關閉使用mdns_socket_open_ipv4
或mdns_socket_open_ipv6
開啟的套接字。
若要開啟/設定套接字以進行一次性查詢,您可以傳遞一個空指標套接字位址,或將傳遞的套接字位址中的連接埠設為0。定到隨機的臨時本地UDP 連接埠一次查詢。進行一次性查詢時,不應綁定到連接埠 5353(有關詳細信息,請參閱 RFC)。
要開啟/設定服務的套接字,回應傳入的查詢,您需要傳入套接字位址結構,並將連接埠設為 5353(由標頭中的 MDNS_PORT 定義)。您不能選擇任何其他端口,否則您將不會收到任何傳入查詢。
若要在預設網路介面上進行發現或查詢,您可以在套接字建立/設定函數中傳遞空指標作為套接字位址。這會將套接字綁定到預設網路介面。否則,您應該列舉可用的介面並將適當的套接字位址傳遞給建立/設定函數。請參閱mdns.c
中的範例程序,以了解針對 IPv4 和 IPv6 執行此操作的範例實作。
如果要對傳入查詢進行 mDNS 服務回應,則不需要枚舉介面來對所有介面進行服務回應,因為套接字會從所有介面接收資料。有關為 IPv4 和 IPv6 設定服務套接字的範例,請參閱mdns.c
中的範例程式。
若要傳送 DNS-SD 服務發現請求,請使用mdns_discovery_send
。這將發送單一多播封包( _services._dns-sd._udp.local.
的單一 PTR 問題記錄)請求單播回應。
若要讀取發現回應,請使用mdns_discovery_recv
。自上次呼叫以來收到的所有記錄都將透過管道傳輸到函數呼叫中提供的回調。條目類型將為MDNS_ENTRYTYPE_ANSWER
、 MDNS_ENTRYTYPE_AUTHORITY
和MDNS_ENTRYTYPE_ADDITIONAL
之一。
若要傳送單一記錄的一次性 mDNS 查詢,請使用mdns_query_send
。這將為給定的記錄和名稱發送單一多播封包(例如_http._tcp.local.
的 PTR 記錄)。您可以選擇傳入查詢的查詢 ID,以便稍後過濾回應(即使 RFC 不鼓勵這樣做),或傳遞 0 以完全相容。此函數傳回與此查詢關聯的查詢 ID,如果該查詢 ID 非零,則可用於過濾mdns_query_recv
中的回應。如果套接字綁定到連接埠 5353,則請求多播回應,否則請求單播回應。
若要讀取查詢回應,請使用mdns_query_recv
。自上次呼叫以來收到的所有記錄都將透過管道傳輸到函數呼叫中提供的回調。如果query_id
參數非零,則函數將過濾掉查詢 ID 與給定查詢 ID 不符的任何回應。條目類型將為MDNS_ENTRYTYPE_ANSWER
、 MDNS_ENTRYTYPE_AUTHORITY
和MDNS_ENTRYTYPE_ADDITIONAL
之一。
請注意,為來自臨時連接埠的一次性查詢而開啟的套接字不會收到任何未經請求的答案(通告),因為這些答案是在連接埠 5353 上作為多播發送的。
要在同一個資料包中傳送多個查詢,請使用mdns_multiquery_send
,它接受一個陣列以及要查詢的服務名稱和記錄類型的計數。
若要偵聽傳入的DNS-SD 請求和mDNS 查詢,可以透過在呼叫套接字開啟/設定函數時傳遞0 作為套接字位址來在預設介面上開啟/設定套接字(套接字將從所有網路介面接收資料)。然後在收到傳入資料的通知時呼叫mdns_socket_listen
,或透過設定阻塞模式並呼叫mdns_socket_listen
進行阻塞,直到資料可用並被解析為止。
傳遞給回呼的條目類型將為MDNS_ENTRYTYPE_QUESTION
,記錄類型指示要回應的記錄。此範例程式回應 SRV、PTR、A 和 AAAA 記錄。使用mdns_string_extract
函數取得所要求的服務記錄的名稱字串。
如果服務記錄名稱為_services._dns-sd._udp.local.
您應該使用mdns_discovery_answer
傳送您提供的服務 (DNS-SD) 的記錄。
如果服務記錄名稱是您提供的服務,請根據問題中的回應類型標誌使用mdns_query_answer_unicast
或mdns_query_answer_multicast
來傳送回服務詳細資訊以回應查詢。
有關如何處理給定函數的參數的更多詳細信息,請參閱測試可執行檔實作。
如果您提供 mDNS 服務在連接埠 5353 上偵聽和回答查詢,我們鼓勵您在服務啟動時發送公告(作為主動答覆)。使用mdns_announce_multicast
在啟動時宣布服務的記錄,並使用mdns_goodbye_multicast
在終止時宣布服務結束。
mdns.c
檔案包含使用該程式庫執行 DNS-SD 和 mDNS 查詢的測試可執行實作。編譯為可執行檔並執行以查看發現、查詢和服務模式的命令列選項。
cl mdns.c /Zi /Fdmdns.pdb /link /out:mdns.exe ws2_32.lib iphlpapi.lib
gcc -o mdns mdns.c
clang -o mdns mdns.c
FetchContent
一起使用或安裝並find_package
mdns/20200130
,並find_package
-> https://conan.io/center/mdns/20200130vcpkg install mdns
和find_package