توفر هذه المكتبة رأسًا فقط عبر منصة mDNS ومكتبة DNS-DS في لغة C. أحدث كود المصدر متاح دائمًا على
https://github.com/mjansson/mdns
تم وضع هذه المكتبة في الملكية العامة؛ يمكنك إعادة توزيعه و/أو تعديله دون أي قيود.
تم الإنشاء بواسطة ماتياس يانسون (@maniccoder)
سيرفر الديسكورد للمناقشات 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 محلي عشوائي سريع الزوال كما هو مطلوب بواسطة RFCs لـ استعلامات طلقة واحدة. يجب ألا ترتبط بالمنفذ 5353 عند إجراء استعلامات لمرة واحدة (راجع RFC للحصول على التفاصيل).
لفتح/إعداد المقبس للخدمة، والرد على الاستعلامات الواردة، تحتاج إلى تمرير بنية عنوان مأخذ التوصيل مع تعيين المنفذ على 5353 (المحدد بواسطة MDNS_PORT في الرأس). لا يمكنك اختيار أي منفذ آخر وإلا فلن تتلقى أي استفسارات واردة.
للقيام بالاكتشاف أو الاستعلامات على واجهة الشبكة الافتراضية، يمكنك تمرير مؤشر فارغ كعنوان مأخذ توصيل في وظائف إنشاء/إعداد مأخذ التوصيل. سيؤدي هذا إلى ربط المقبس بواجهة الشبكة الافتراضية. وإلا فيجب عليك تعداد الواجهات المتوفرة وتمرير عنوان مأخذ التوصيل المناسب إلى وظيفة الإنشاء/الإعداد. راجع مثال البرنامج في mdns.c
للحصول على مثال لتنفيذ ذلك لكل من IPv4 وIPv6.
إذا كنت تريد إجراء استجابة خدمة mDNS للاستعلامات الواردة، فلن تحتاج إلى تعداد الواجهات للقيام باستجابة الخدمة على جميع الواجهات حيث تتلقى المقابس البيانات من جميع الواجهات. راجع البرنامج النموذجي في mdns.c
للحصول على مثال لإعداد مقبس خدمة لكل من IPv4 وIPv6.
لإرسال طلب اكتشاف خدمة DNS-SD استخدم mdns_discovery_send
. سيؤدي هذا إلى إرسال حزمة بث متعدد واحدة (سجل سؤال PTR واحد لـ _services._dns-sd._udp.local.
) تطلب استجابة البث الأحادي.
لقراءة استجابات الاكتشاف، استخدم mdns_discovery_recv
. سيتم إرسال جميع السجلات المستلمة منذ آخر مكالمة إلى رد الاتصال المقدم في استدعاء الوظيفة. سيكون نوع الإدخال واحدًا من MDNS_ENTRYTYPE_ANSWER
و MDNS_ENTRYTYPE_AUTHORITY
و MDNS_ENTRYTYPE_ADDITIONAL
.
لإرسال استعلام mDNS لمرة واحدة لسجل واحد، استخدم mdns_query_send
. سيؤدي هذا إلى إرسال حزمة بث متعدد واحدة للسجل والاسم المحددين (على سبيل المثال، سجل PTR لـ _http._tcp.local.
). يمكنك بشكل اختياري تمرير معرف استعلام للاستعلام لتصفية الاستجابات لاحقًا (على الرغم من أن RFC لا ينصح بذلك)، أو تمرير 0 لتكون متوافقًا تمامًا. تقوم الدالة بإرجاع معرف الاستعلام المرتبط بهذا الاستعلام، والذي يمكن استخدامه إذا لم يكن صفرًا لتصفية الاستجابات في mdns_query_recv
. إذا كان المقبس مرتبطًا بالمنفذ 5353، فسيتم طلب استجابة البث المتعدد، وإلا فسيتم طلب استجابة البث الأحادي.
لقراءة استجابات الاستعلام، استخدم mdns_query_recv
. سيتم إرسال جميع السجلات المستلمة منذ آخر مكالمة إلى رد الاتصال المقدم في استدعاء الوظيفة. إذا كانت المعلمة query_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