このライブラリは、C でヘッダーのみのクロスプラットフォーム mDNS および DNS-DS ライブラリを提供します。最新のソース コードは常に次の場所で入手できます。
https://github.com/mjansson/mdns
このライブラリはパブリック ドメインに置かれています。制限なく再配布したり変更したりできます。
マティアス・ヤンソン (@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 に設定します。これにより、ソケットは、RFC の要求に従って、ランダムな一時的なローカル UDP ポートにバインドされます。ワンショットクエリ。ワンショット クエリを実行するときは、ポート 5353 にバインドしないでください (詳細については RFC を参照してください)。
サービス用にソケットを開いてセットアップし、受信クエリに応答するには、ポートを 5353 (ヘッダーの MDNS_PORT で定義) に設定したソケット アドレス構造体を渡す必要があります。他のポートを選択することはできません。そうしないと、受信クエリを受信できなくなります。
デフォルトのネットワーク インターフェイスで検出またはクエリを実行するには、ソケットの作成/セットアップ関数でソケット アドレスとしてヌル ポインタを渡すことができます。これにより、ソケットがデフォルトのネットワーク インターフェイスにバインドされます。それ以外の場合は、使用可能なインターフェイスを列挙し、適切なソケット アドレスを作成/セットアップ関数に渡す必要があります。 IPv4 と IPv6 の両方でこれを行う実装例については、 mdns.c
のプログラム例を参照してください。
受信クエリに対して 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 を返します。ゼロ以外の場合は、 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.
提供するサービス (DNS-SD) のレコードを送信するには、 mdns_discovery_answer
を使用する必要があります。
サービス レコード名が提供するサービスである場合は、質問内の応答タイプ フラグに応じてmdns_query_answer_unicast
またはmdns_query_answer_multicast
を使用して、クエリへの応答としてサービスの詳細を送り返します。
指定された関数のパラメーターを処理する方法の詳細については、テスト実行可能ファイルの実装を参照してください。
ポート 5353 でクエリをリッスンして応答する mDNS サービスを提供する場合は、サービスの開始時にアナウンスを (一方的な応答として) 送信することをお勧めします。起動時にサービスのレコードをアナウンスするには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
で cmake を使用するか、インストールしてfind_package
使用するmdns/20200130
で conan を使用し、 find_package
-> https://conan.io/center/mdns/20200130vcpkg install mdns
およびfind_package