Bonjour手把手搭建一:mDNS(apple & multicastdns.org)

mDNS(Multicast DNS)——From Apple

https://support.apple.com/kb/TA20999?locale=zh_CN&viewlocale=en_US

Multicast DNS, one of the features incorporated in Bonjour, which was introduced in Mac OS X 10.2.

Bonjour的一個新特性,在Mac OS X10.2後引入,以前叫作Rendezvous

Multicast DNS is one of the features of Bonjour (formerly "Rendezvous"), included in Mac OS X 10.2 or later. It allows you to connect via Internet protocol (IP) to other computers on a local network by name, rather than a numbered address.

允許通過IP協議,在同一網段,利用名字連接,而不是數字IP地址

On the Internet at large, a DNS name such as "www.apple.com" must be resolved to a numbered IP address before your computer can connect to the server. A domain name system (DNS) server normally provides this name resolution service for your computer. Your Internet service provider or network administrator normally provides a local DNS server for your use.

在global網絡裏,DNS server提供了地址解析服務。


Conversely, Multicast DNS allows computers on a local network, such as home or small office, to look up each others' names and addresses without a DNS server. Each computer knows its own name and responds to requests for that name automatically via IP multicast.
mDNS是相對於本地網絡來說的,通過主機名字,利用IP多播,發送請求。


Anywhere that a you could normally use a DNS name such as "www.apple.com", you could instead enter the Bonjour name of the computer on the local network. To indicate that the name should be looked up using local multicast instead of a standard DNS query, all Bonjour host names end with the extension ".local." This helps avoid confusion between names that are local Bonjour computer names ("mycomputer.local") and globally unique DNS names ("www.apple.com").

爲了避免衝突,本地bonjour用.local後綴,區分於www.xxx.com。

If you use local Bonjour computer names frequently and do not want to explicitly type ".local." every time, then this extension may be added to the Search Domains field in the Network preference pane. Click the TCP/IP tab in the Network preference pane to access the Search Domains field. Be sure you have selected the correct network port from the Show menu.

如果你要默認使用.local,在網絡裏面配置設置,並設置對端口。


For more information about Multicast DNS in general, see the Multicast DNS website (http://www.multicastdns.org/).

Note: If you have set up a private DNS server that resolves names in the .local domain, computers using Mac OS X 10.2 will not use the DNS server to resolve these names. This may result in unexpected failures to connect to hostnames defined by your server. You should use a different domain, such as .home, .office, or .lan for DNS on private networks.

注意,如果你之前配置過本地DNS server,請用與.local不同的後綴。

 

Multicast DNS——From multicastdns.org

Multicast DNS is a way of using familiar DNS programming interfaces, packet formats and operating semantics, in a small network where no conventional DNS server has been installed.

mDNS是一種在本地網絡,沒有DNS服務器的情況下,使用DNS編程接口,包格式,操作語義的一種方式。(Any idea?

Multicast DNS is a joint effort by participants of the IETF Zero Configuration Networking (zeroconf) and DNS Extensions (dnsext) working groups. The requirements are driven by the Zeroconf working group; the implementation details are a chartered work item for the DNSEXT group. Most of the people working on mDNS are active participants of both working groups.

mDNS的貢獻者。

While the requirements for Zeroconf name resolution could be met by designing an entirely new protocol, it is better to provide this functionality by making minimal changes to the current standard DNS protocol. This saves application programmers from having to learn new APIs, and saves application programmers from having to write application code two different ways — one way for large configured networks and a different way for small Zeroconf networks. It means that most current applications need no changes at all to work correctly using mDNS in a Zeroconf network. It also means that engineers do not have to learn an entirely new protocol, and current network packet capture tools can already decode and display DNS packets, so they do not have to be updated to understand new packet formats.

爲什麼不設計一個新的協議?因爲爲了程序員不用學習新的協議,也不用在目前的DNS代碼裏面做大改變,目前的抓包軟件也能正確解析DNS包。

 

http://www.multicastdns.org/

-----------------------------------------------------
https://www.cnblogs.com/yuweifeng/p/6409182.html

DNS(Domain Name System,域名系統)因特網上作爲域名和IP地址相互映射的一個分佈式數據庫,能夠使用戶更方便的訪問互聯網,而不用去記住能夠被機器直接讀取的IP數串。通過主機名,最終得到該主機名對應的IP地址的過程叫做域名解析(或主機名解析)。DNS協議運行在UDP協議之上,使用端口號53。在RFC文檔中RFC 2181對DNS有規範說明,RFC 2136對DNS的動態更新進行說明,RFC 2308對DNS查詢的反向緩存進行說明。

一、mDNS    具體協議規範地址如下 : http://www.ietf.org/rfc/rfc6762.txt

mdns 即多播dns(Multicast DNS),mDNS主要實現了在沒有傳統DNS服務器的情況下使局域網內的主機實現相互發現和通信,使用的端口爲5353,遵從dns協議,使用現有的DNS信息結構、名語法和資源記錄類型。並且沒有指定新的操作代碼或響應代碼。

 

在局域網中,設備和設備之前相互通信需要知道對方的ip地址的,大多數情況,設備的ip不是靜態ip地址,而是通過dhcp 協議動態分配的ip 地址,如何設備發現呢,就是要mdns大顯身手,例如:現在物聯網設備和app之間的通信,要麼app通過廣播,要麼通過組播,發一些特定信息,感興趣設備應答,實現局域網設備的發現,當然mdns 比這強大的多

1.mDNS 基於 UDP 協議。

組播地址: 組播地址使用的是D類地址,地址範圍爲:224.0.0.0—239.255.255.255

 

2.mdns 工作原理簡單描述:

 

mdns 使用組播地址爲: 224.0.0.251 (ipv6: FF02::FB) 端口爲5353,mdns 是用於局域網內部的,並且主機的域名爲.local 結尾,每個進入局域網的主機,如果開啓了mDNS服務的話,都會向局域網內的所有主機組播一個消息,我是誰(域名),和我的IP地址是多少。然後其他有mdns服務的主機就會響應,也會告訴你,它是誰(域名),它的IP地址是多少。 當然設備需要服務時,就是使用mdns 查詢域名對對應的ip地址,對應的設備收到該報文後同樣通過組播方式應答,此時其他主機設備也是可以收到該應答報文,其他主機也會記錄域名和ip 以及ttl 等,更新緩存

 

比如,A主機進入局域網,開啓了 mDNS 服務,並向 mDNS 服務註冊以下信息:我提供 FTP 服務,我的IP是 192.168.1.101,端口是 21。當B主機進入局域網,並向 B 主機的 mDNS 服務請求,我要找局域網內 FTP 服務器,B主機的 mDNS 就會去局域網內向其他的 mDNS 詢問,並且最終告訴你,有一個IP地址爲 192.168.1.101,端口號是 21 的主機,也就是 A 主機提供 FTP 服務,所以 B 主機就知道了 A 主機的 IP 地址和端口號了。

 

大概的原理就是這樣子,mDNS提供的服務要遠遠多於這個,當然服務多但並不複雜。

3.mDNSResponder與Bonjour的關係:

The mDNSResponder project is a component of Bonjour,

Apple's ease-of-use IP networking initiative:

<http://developer.apple.com/bonjour/>

Bonjour是法語中的Hello之意。它是Apple公司爲基於組播域名服務(multicast DNS)的開放性零配置網絡標準所起的名字。使用Bonjour的設備在網絡中自動組播它們自己的服務信息並監聽其它設備的服務信息。設備之間就像在打招呼,這也是該技術命名爲Bonjour的原因。Bonjour使得局域網中的系統和服務即使在沒有網絡管理員的情況下也很容易被找到。

舉一個簡單的例子:在局域網中,如果要進行打印服務,必須先知道打印服務器的IP地址。此IP地址一般由IT部門的人負責分配,然後他還得全員發郵件以公示此地址。有了Bonjour以後,打印服務器自己會依據零配置網絡標準在局域網內部找到一個可用的IP並註冊一個打印服務,名爲“print service”之類的。當客戶端需要打印服務時,會先搜索網絡內部的打印服務器。由於不知道打印服務器的IP地址,客戶端只能根據諸如"print service"的名字去查找打印機。在Bonjour的幫助下,客戶端最終能找到這臺註冊了“print service”名字的打印機,並獲得它的IP地址以及端口號。

從Bonjour角度來看,該技術主要解決了三個問題:

  • Addressing:即爲主機分配IP。Bonjour的Addressing處理比較簡單,即每個主機在網絡內部的地址可選範圍內找一個IP,然後查看網絡內部是否有其他主機再用。如果該IP沒有被分配的話,它將使用此IP。
  • Naming:Naming解決的是host名和IP地址的對應關係。Bonjour採用的是Multiple DNS技術,即DNS查詢消息將通過UDP組播方式發送。一旦網絡內部某個機器發現查詢的機器名和自己設置的一樣,就回復這條請求。此外,Bonjour還拓展了MDNS的用途,即除了能查找host外,還支持對service的查找。不過,Bonjour的Naming有一個限制,即網絡內部不能有重名的host或service。
  • Service Discovery:SD基於上面的Naming工作,它使得應用程序能查找到網絡內部的服務,並解析該服務對應的IP地址和端口號。應用程序一旦得到服務的IP地址和端口號,就可以直接和該服務建立交互關係。

Bonjour技術在Mac OS以及Itunes、Iphone上都得到了廣泛應用。爲了進一步推廣,Apple通過開源工程mdnsresponder將其開源出來。在Windows平臺上,它將生成一個後臺程序mdnsresponder。在Android平臺上(或者說支持POSIX的Linux平臺)它是一個名爲mdnsd的程序。不過,不論是mdnsresponder還是mdnsd,應用開發者要做的僅僅是利用Bonjour的API向它們發起服務註冊、服務查詢和服務解析等請求並接收來自它們的處理結果。

下面我們將介紹Bonjour API中使用最多的三個函數,它們分別是服務註冊、服務查詢和服務解析。理解這三個函數的功能也是理解MDnsSdListener的基礎。

使用Bonjour API必須包含如下的頭文件和動態庫,並連接到:

#include <dns_sd.h>  //必須包含此頭文件

libmdnssd.so  //鏈接到此so

Bonjour中,服務註冊的API爲DNSServiceRegister,原型如圖1所示:

                    

圖1  DNSServiceRegister原型

該函數的解釋如下:

  • sdRef:代表一個未初始化的DNSService實體。其類型DNSServiceRef是指針。該參數最終由DNSServiceRegister函數分配內存並初始化。
  • flags:表示當網絡內部有重名服務時的衝突處理。默認是按順序修改服務名。例如要註冊的服務名爲“printer”,當檢測到重名衝突時,就可改名爲“printer(1)”。
  • interfaceIndex:表示該服務輸出到主機的哪些網絡接口上。值-1表示僅對本機支持,也就是該服務的用在loop接口上。
  • name:表示服務名,爲空的話就取機器名。
  • regtype:服務類型,用字符串表達。Bonjour要求格式爲"_服務名._傳輸協議",例如"_ftp._tcp"。目前傳輸協議僅支持TCP和UDP。
  • domian和host一般都爲空。
  • port表示該服務的端口。如果爲0的話,Bonjour會自動分配一個。
  • txtLen以及txtRecord字符串用來描述該服務。一般都設置爲空。
  • callBack:設置回調函數。該服註冊的請求結果都會通過它回調給客戶端。
  • context:上下文指針,由應用程序設置。

當客戶端需要搜索網絡內部特定服務時,需要使用DNSServiceBrowser API,其原型如圖2所示:

                     

圖2  DNSServiceBrowser原型

其中:

  • sdref、interfaceIndex、regtype、domain以及context含義與DNSServiceRegister一樣。
  • flags:在本函數中沒有作用。
  • callBack:爲DNSServiceBrowser處理結果的回調通知接口。

當客戶端想獲得指定服務的IP和端口號時,需要使用DNSServiceResolve API,其原型如圖3所示:

                      

圖3  DNSServiceResolve原型

其中:

  • name、regtype和domain都從DNSServiceBrowse函數的處理結果中獲得。
  • callBack用於通知DNSServiceResolve的處理結果。該回調函數將返回服務的IP地址和端口號。

如果需要了解Bonjour安卓中的使用方法及原理,請閱讀該部分的原文: http://blog.csdn.net/innost/article/details/8629139

 

4.Linux中的使用方法:

附件提供了mDNS的源碼,分析源碼我們就可以知道如何編譯安裝以及如何使用:

在mDNSResponder-107.5\mDNSPosix目錄中的Responder.c文件中的main我們可以看到

調用了PrintUsage函數中提供了用法說明:

根據上面的描述,使用shell命令調用的例子:

//mDNSResponderPosix來源於bonjour,服務註冊

sprintf(buf, "mDNSResponderPosix -n %s -t _ipc_http._tcp. " "-d local. -p 5959 &", gpCC->ccArg.pDevId);//-n 服務名,-t 服務類型,-d域名,-p端口號,

    system(buf);//後臺運行

再看main函數中執行過程:

 

初始化後調用了RegisterOurServices函數把要提供的服務註冊進去(追蹤下去就可以看到最終調用了mdnscore.c中的mDNS_RegisterService函數):

 

mDNSResponder介紹與移植

https://blog.csdn.net/yuangc/article/details/101676976

mDNSResponder是蘋果的Bonjour項目的一部分。 Bonjour是法語“你好”的意思。
Bonjour軟件源自正IETF零配置網絡工作。零配置工作有三個要求:
1.分配IP地址(即使沒有分配DHCP服務器的IP地址)
2.提供名稱到地址的轉換(即使沒有DNS服務器)
3.在網絡上發現相關的網絡服務(同樣沒有其他的基礎協議支持)

也就是說不需要以上DNS等相關的服務的支持,通過零配置直接完成這些任務。厲害吧?
對於1,通過自分配的本地鏈接地址實現。
對於2,通過多播(mDNS)發送類似DNS的查詢來滿足。
對於3,通過DNS Service Dicsovery(DNS-SD)滿足。

自分配的本地鏈接地址自1998年, 在Windows '98和Mac OS 8.5中shouci出現。當然在其他平臺上也支持。
mDNSResponder

mDNSResponder項目實現了上面的2和3。其中,m是Multicast縮寫。即使用戶沒有設置傳統的DNS服務器,用戶也能夠使用服務名稱(比如www.sohu.com),而不是點分十進制IP地址(suhu的IP是122.13.86.100)來標識主機。它還爲用戶無需事先了解服務的細節,就可以發現網絡上正在播發什麼服務,也無需配置機器。

選擇名稱“ mDNS”,是因爲該協議類似於常規DNS。不過,mDNS和DNS的主要區別在於:
mDNS查詢是通過多播發送到所有本地主機,而不是通過單播發送到特定的已知服務器。本地鏈接上的每個主機都運行一個mDNSResponder,該DNS響應器不斷監聽那些多播查詢,如果mDNSResponder接收到自己關注的查詢,則做出響應。

mDNS協議使用與單播DNS相同的數據包格式,相同的名稱結構和相同的DNS記錄類型。這部分的主要區別在於:
1.查詢被髮送到不同的UDP端口(5353,而不是53),並通過多播發送到地址224.0.0.251。
2.所有“ mDNS”名稱都以“ .local”結尾。當用戶鍵入“ yourcomputer.local”時。進入他們的Web瀏覽器時,就會顯示“ .local”。.local告訴主機OS應該使用本地多播查找該名稱,而不是通過將該名稱發送給互聯網的DNS服務。這有助於用戶區分特定名稱是廣域網的(例如“ www.apple.com”)還是僅僅在本地(例如“ yourcomputer.local”)。
mDNSResponder源代碼

由於Apple認爲公開這部分代碼比較好,可以供其他開發人員使用。這部分代碼可以兼容不同種類的OS。
典型的mDNS程序包含三個組件:
在這裏插入圖片描述
“ mDNS Core”層在所有應用程序和所有操作系統都是相同的。
“Platform Support”層提供了特定於每個平臺的必要支持例程,例如,調用哪個例程以發送UDP數據包,調用哪個例程以加入多播組等等。
“Application”層可以執行特定應用程序想要執行的任何操作。 它調用“ mDNS Core”層提供的例程來執行所需的功能:
*發佈服務,
*瀏覽特定服務類型的命名實例
*將命名實例解析爲特定的IP地址和端口號,
移植

Apple當前爲Mac OS 9,Mac OS X,Microsoft Windows,VxWorks以及POSIX平臺(例如Linux,Solaris,FreeBSD等)提供“平臺支持”層。
注意,OS X已經提供了mDNS 對應的系統調用,因此不需要移植這份代碼。

如果每個應用程序將mDNSResponder代碼鏈接到應用內部中,那麼最終將遇到如下圖所示的情況:
在這裏插入圖片描述

這樣效率不高。其實OS X提供了一種通用的系統服務,可以通過“ /usr/include/dns_sd.h”API對其進行訪問就ok了。所以實際上每個應用都訪問daemon程序,只用一份就好了:
在這裏插入圖片描述
如果希望在內部使用,不用第三方的服務,可以參照上圖來移植。在 mDNSPosix目錄有具體的說明。
在舊版本的編譯器移植

有的編譯器太舊,不支持雙斜槓的註釋://,那麼就要手動改了。比如:
打開BBEdit:

    打開 “Find” 對話選擇 “Use Grep”
    搜索 : ([^:])//(.*)
    替換: \1/*\2 */
    將mDNSResponder代碼拖到多文件搜索界面
    選擇"Replace All" 替換所有。

對於面向更多命令行,可以進入代碼目錄,執行下面的命令:

find mDNSResponder ( -name *.c* -or -name *.h ) -exec sed -i .orig -e ‘s,^//(.),/\1 /,’ -e '//*/!s,([^:])//(.),\1/*\2 */,’ {} ;
mDNSPosix

mDNSPosix是Apple的mDNS到Posix平臺的移植。

目錄:

mDNSCore-包含核心mDNS代碼的目錄。該代碼是用純ANSI C編寫的,並被證明具有很高的可移植性。每個平臺都需要此核心協議引擎代碼。

mDNSShared-一個包含有用代碼的目錄,該代碼不是主協議引擎本身的核心。

mDNSPosix-特定於Posix平臺的文件:Linux,Solaris,FreeBSD,NetBSD,OpenBSD等。

Clients -客戶端代碼示例,顯示如何將API用於守護程序提供的服務。
編譯代碼

在mDNSPosix目錄,make對應的系統名稱:
make os=linux
之後在mDNSPosix/build/prod目錄會生成下面的文件:

.
├── libdns_sd.so
├── libnss_mdns-0.2.so
├── mDNSClientPosix
├── mdnsd
├── mDNSIdentify
├── mDNSNetMonitor
├── mDNSProxyResponderPosix
└── mDNSResponderPosix

通用平臺使用(例如在臺式計算機上):
-mdnsd
-libmdns
-nss_mdns(有關nss_mdns,請參見nss_ReadMe.txt)
專用平臺使用:
-mDNSClientPosix
-mDNSResponderPosix
-mDNSProxyResponderPosix
測試工具:
-dns-sd命令行工具(來自“Client”文件夾)
-mDNSNetMonitor
-mDNSIdentify
運行說明

在這裏插入圖片描述
mdnsd分爲三個部分。

o mDNSCore是主要的協議引擎
o mDNSPosix.c提供了在Posix OS上的對應移植
o uds_daemon.c將Unix域套接字接口,導出到mDNSCore提供的服務

客戶端應用程序與libmdns鏈接,libmdns實現dns_sd.h頭文件中定義的功能,並實現IPC協議,該協議用於通過Unix Domain Socket接口與守護程序進行通信。

嚴格來說,nss_mdns只是mdnsd的另一個客戶端,就像其他任何客戶端一樣與libmdns鏈接。只不過它在多播DNS的正常運行中起着核心作用,因此它與其他必要的系統支持組件一起編譯安裝。
小型嵌入式系統客戶端

有時候需要在極小的系統下支持mdns,但是系統資源有限,這時候可以取消uds_daemon和libmdns層。直接調用core的接口。下面是一些簡要的說明,如果沒有這樣的需求就直接跳過不用看了。
在這裏插入圖片描述
不過,這樣工作量會比較大。
1.應用程序調用mDNS_Init,後者調用平臺(mDNSPlatformInit)。

    mDNSPlatformInit獲取接口列表(get_ifi_info),並向核心註冊每個接口(mDNS_RegisterInterface)。它還爲每個接口創建一個多播套接字(SetupSocket)。

3.然後,應用程序反覆調用select()來處理文件描述符事件。在每次調用select()之前,應用程序都會調用mDNSPosixGetFDSet()來給mDNSPosix.ca機會將其自己的文件描述符添加到集合中,然後在select()返回之後, 調用mDNSPosixProcessFDSet()來使 接收並處理數據包。

4.當核心需要發送UDP數據包時, 調用mDNSPlatformSendUDP。該例程查找與內核請求的源地址相對應的接口,並使用爲該接口創建的UDP套接字發送數據報。如果套接字是流發送側控制的,則丟棄數據包。

5.當SocketDataReady運行時,它使用複雜的例程“ recvfrom_flags”來接收數據包。

另外,如果決定在平臺中使用線程,注意要實現mDNSPlatformLock()和mDNSPlatformUnlock()調用。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章