Diese Bibliothek stellt eine plattformübergreifende mDNS- und DNS-DS-Bibliothek nur für Header in C bereit. Der neueste Quellcode ist immer unter verfügbar
https://github.com/mjansson/mdns
Diese Bibliothek ist gemeinfrei; Sie können es ohne Einschränkungen weiterverbreiten und/oder ändern.
Erstellt von Mattias Jansson (@maniccoder)
Discord-Server für Diskussionen https://discord.gg/M8BwTQrt6c
Die Bibliothek führt DNS-SD-Erkennung und -Dienste sowie einmalige mDNS-Abfragen und -Antworten für einzelne Datensätze durch. Die Bibliothek nimmt keine Speicherzuweisungen vor, alle verwendeten Puffer müssen vom Aufrufer übergeben werden. Benutzerdefinierte Daten zur Verwendung bei der Verarbeitung können mithilfe eines undurchsichtigen Benutzerdatenzeigers weitergegeben werden.
Die ausführbare Testdatei mdns.c
demonstriert die Verwendung aller Funktionen, einschließlich Erkennung, Abfrage und Serviceantwort. Die Dokumentation ist hier bewusst spärlich gehalten, der Beispielcode ist gut dokumentiert und sollte alle Details enthalten.
Der Socket für die mDNS-Kommunikation kann entweder von der Bibliothek mithilfe von mdns_socket_open_ipv4
oder mdns_socket_open_ipv6
oder durch Initialisieren eines vorhandenen Sockets mit mdns_socket_setup_ipv4
oder mdns_socket_setup_ipv6
geöffnet werden. Die Socket-Öffnungs-/Setup-Funktionen initialisieren den Socket mit Multicast-Mitgliedschaft (einschließlich Loopback) und setzen ihn in den nicht blockierenden Modus.
Rufen Sie mdns_socket_close
auf, um einen mit mdns_socket_open_ipv4
oder mdns_socket_open_ipv6
geöffneten Socket zu schließen.
Um den Socket für einmalige Abfragen zu öffnen/einzustellen, können Sie eine Nullzeiger-Socket-Adresse übergeben oder den Port in der übergebenen Socket-Adresse auf 0 setzen. Dadurch wird der Socket an einen zufälligen kurzlebigen lokalen UDP-Port gebunden, wie in den RFCs für erforderlich einmalige Abfragen. Sie sollten NICHT an Port 5353 binden, wenn Sie einmalige Abfragen durchführen (Einzelheiten finden Sie im RFC).,
Um den Socket für den Dienst zu öffnen/einrichten und auf eingehende Anfragen zu reagieren, müssen Sie eine Socket-Adressstruktur übergeben, wobei der Port auf 5353 eingestellt ist (definiert durch MDNS_PORT im Header). Sie können keinen anderen Port auswählen, sonst erhalten Sie keine eingehenden Anfragen.
Um Erkennungen oder Abfragen auf der Standardnetzwerkschnittstelle durchzuführen, können Sie in den Socket-Erstellungs-/Setup-Funktionen einen Nullzeiger als Socket-Adresse übergeben. Dadurch wird der Socket an die Standardnetzwerkschnittstelle gebunden. Andernfalls sollten Sie die verfügbaren Schnittstellen aufzählen und die entsprechende Socket-Adresse an die Funktion „create/setup“ übergeben. Eine Beispielimplementierung hierfür für IPv4 und IPv6 finden Sie im Beispielprogramm in mdns.c
Wenn Sie eine mDNS-Dienstantwort auf eingehende Abfragen ausführen möchten, müssen Sie keine Schnittstellen aufzählen, um eine Dienstantwort auf allen Schnittstellen auszuführen, da Sockets Daten von allen Schnittstellen empfangen. Ein Beispiel für die Einrichtung eines Service-Sockets für IPv4 und IPv6 finden Sie im Beispielprogramm in mdns.c
Um eine DNS-SD-Diensterkennungsanfrage zu senden, verwenden Sie mdns_discovery_send
. Dadurch wird ein einzelnes Multicast-Paket (einzelner PTR-Fragedatensatz für _services._dns-sd._udp.local.
) gesendet, der eine Unicast-Antwort anfordert.
Um Erkennungsantworten zu lesen, verwenden Sie mdns_discovery_recv
. Alle seit dem letzten Aufruf empfangenen Datensätze werden an den im Funktionsaufruf bereitgestellten Rückruf weitergeleitet. Der Eintragstyp ist einer von MDNS_ENTRYTYPE_ANSWER
, MDNS_ENTRYTYPE_AUTHORITY
und MDNS_ENTRYTYPE_ADDITIONAL
.
Um eine einmalige mDNS-Abfrage für einen einzelnen Datensatz zu senden, verwenden Sie mdns_query_send
. Dadurch wird ein einzelnes Multicast-Paket für den angegebenen Datensatz und Namen gesendet (z. B. PTR-Datensatz für _http._tcp.local.
). Sie können optional eine Abfrage-ID für die Abfrage zum späteren Filtern von Antworten übergeben (auch wenn dies vom RFC nicht empfohlen wird) oder 0 übergeben, um vollständig konform zu sein. Die Funktion gibt die dieser Abfrage zugeordnete Abfrage-ID zurück. Wenn sie ungleich Null ist, kann sie zum Filtern von Antworten in mdns_query_recv
verwendet werden. Wenn der Socket an Port 5353 gebunden ist, wird eine Multicast-Antwort angefordert, andernfalls eine Unicast-Antwort.
Um Abfrageantworten zu lesen, verwenden Sie mdns_query_recv
. Alle seit dem letzten Aufruf empfangenen Datensätze werden an den im Funktionsaufruf bereitgestellten Rückruf weitergeleitet. Wenn der Parameter query_id
ungleich Null ist, filtert die Funktion alle Antworten mit einer Abfrage-ID heraus, die nicht mit der angegebenen Abfrage-ID übereinstimmt. Der Eintragstyp ist einer von MDNS_ENTRYTYPE_ANSWER
, MDNS_ENTRYTYPE_AUTHORITY
und MDNS_ENTRYTYPE_ADDITIONAL
.
Beachten Sie, dass ein Socket, der für einmalige Abfragen von einem temporären Port geöffnet ist, keine unaufgeforderten Antworten (Ankündigungen) erhält, da diese als Multicast an Port 5353 gesendet werden.
Um mehrere Abfragen im selben Paket zu senden, verwenden Sie mdns_multiquery_send
, das ein Array und eine Anzahl von Dienstnamen und Datensatztypen für die Abfrage benötigt.
Um auf eingehende DNS-SD-Anfragen und mDNS-Anfragen zu warten, kann der Socket auf der Standardschnittstelle geöffnet/eingerichtet werden, indem 0 als Socket-Adresse im Aufruf der Socket-Öffnungs-/Setup-Funktionen übergeben wird (der Socket empfängt Daten von allen Netzwerkschnittstellen). Rufen Sie dann mdns_socket_listen
auf, entweder bei Benachrichtigung über eingehende Daten oder indem Sie den Blockierungsmodus festlegen und mdns_socket_listen
zum Blockieren aufrufen, bis Daten verfügbar und analysiert sind.
Der an den Rückruf übergebene Eintragstyp ist MDNS_ENTRYTYPE_QUESTION
und der Datensatztyp gibt an, mit welchem Datensatz geantwortet werden soll. Das Beispielprogramm reagiert auf SRV-, PTR-, A- und AAAA-Datensätze. Verwenden Sie die Funktion mdns_string_extract
, um die Namenszeichenfolge des angeforderten Dienstdatensatzes abzurufen.
Wenn der Dienstdatensatzname _services._dns-sd._udp.local.
Sie sollten mdns_discovery_answer
verwenden, um die Aufzeichnungen der von Ihnen bereitgestellten Dienste zu senden (DNS-SD).
Wenn es sich bei dem Dienstdatensatznamen um einen von Ihnen bereitgestellten Dienst handelt, verwenden Sie je nach Antworttyp-Flag in der Frage mdns_query_answer_unicast
oder mdns_query_answer_multicast
um die Dienstdetails als Antwort auf die Abfrage zurückzusenden.
Weitere Informationen zum Umgang mit den Parametern der angegebenen Funktionen finden Sie in der Testimplementierung der ausführbaren Datei.
Wenn Sie einen mDNS-Dienst bereitstellen, der Port 5353 abhört und Anfragen beantwortet, wird empfohlen, beim Start Ihres Dienstes eine Ankündigung zu senden (als unaufgeforderte Antwort). Verwenden Sie mdns_announce_multicast
um die Datensätze für Ihren Dienst beim Start anzukündigen, und mdns_goodbye_multicast
um das Ende des Dienstes bei Beendigung anzukündigen.
Die Datei mdns.c
enthält eine ausführbare Testimplementierung, die die Bibliothek zum Durchführen von DNS-SD- und mDNS-Abfragen verwendet. Kompilieren Sie es in eine ausführbare Datei und führen Sie es aus, um Befehlszeilenoptionen für Erkennungs-, Abfrage- und Servicemodi anzuzeigen.
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
oder installieren und find_package
mdns/20200130
und find_package
-> https://conan.io/center/mdns/20200130vcpkg install mdns
und find_package