Bonjour 簡介及使用

這兩天抽空做了幾個Bonjour的測試,將我的理解整理了一下和大家分享,希望對大家的工作有幫助,同時,有理解錯誤的地方也請大家校正。

1. Bonjour簡介
BonjourApple推出的零配置網絡協議,主要的目的是在缺少中心服務器的情況下解決網絡設備的IP獲取,名稱解析和服務發現等關鍵問題。
Bonjour這個詞來源於法語,是你好的意思,應該是指遵從這個協議的設備可以通過主動打招呼的形式發現彼此。Bonjour的法語發音大概爲甭油喝,我們不會讀法語,也不會延用法語發音,Bonjour的英語發音大概是幫就而,重音在第一個音節。

2. Bonjour可以做什麼
如上面提到的,Bonjour可以完成的工作主要是在缺少中心服務器的情況下解決IP獲取,名稱解析和服務發現這三個問題。

2.1 IP獲取
在傳統網絡環境下,設備的IP地址通過兩種方式獲取,一種是靜態配置,通過手工方式爲設備指定一個IP地址,一種是動態配置,設備通過路由器的DHCP服務獲得動態的IP地址。
在無中心服務器的網絡環境下,沒有中心服務器提供DHCP服務,用戶手工配置IP地址也很不方便,這就需要一種新的方式來幫助設備獲取IP地址,就是希望設備可以主動爲自己指定一個可用的IP地址。
IPV6環境下,IPV6協議本身就提供了設備自指定IP地址的能力,所以實現很簡單,直接使用IPV6的協議支持就可以了。
IPV4環境下,Bonjour使用了隨機指定IP地址的方法,首先爲設備隨機指定一個屬於本地網段的IP地址,然後檢查該地址在本地是否有衝突,如果有衝突就隨機生成另一個新的IP地址,直到找到可用IP地址爲止。
我在做測試的時候沒有測試這部分,都是使用的DHCP的動態地址。以後有時間測試了這個部分後再和大家分享測試結果。

2.2 名稱解析
在傳統網絡環境下,名稱和IP地址的對應關係是通過DNS服務解析的。當一個設備需要訪問一個域名,如www.abc.com,設備將www.abc.com發給DNS服務器,服務器返回該域名對應的IP地址,設備再使用返回的IP地址對目標服務器進行訪問。
在沒有中心服務器的網絡環境中,沒有DNS服務器提供域名解析服務,名稱解析變成一個嚴重問題。針對這一問題,業界的解決方案是mDNS,中文叫組播DNS”,在標準文檔RFC6762中定義。
組播DNS”的原理很簡單,當一個設備需要解析一個名稱時,如“abc.local.”,這個設備通過UDP協議向本地網絡中的所有設備廣播一個消息,問誰是“abc.local”,本地網絡中如果有一個設備認爲自己是“abc.local”,它就給出響應,說出自己的IP地址。
因爲組播DNS”基於UDP協議,採用廣播消息的方式,所以不需要一箇中心服務器提供DNS解析服務就可以完成本地的名稱解析。
Bonjour也是基於mDNS協議的,不過BonjourmDNS協議上作了擴展,加強了設備響應組播DNS”請求的能力。在Bonjour協議下,應用只需要對某個名稱進行註冊,就可以將響應組播DNS”請求的工作交由底層處理。也就是說在Bonjour協議下,應用不需要偵聽本地網絡的組播DNS”請求並進行響應,這些工作由底層系統完成。
爲了區分全球域名和本地域名,mDNS協議使用“.local.”作爲本地域名的根域名。

2.3 服務發現
當一個提供服務的設備獲取IP地址,並自我指定一個域名後,其實還是不能滿足用戶的需求。因爲用戶需要的是某種服務,如打印服務,web服務,用戶並不關心這些服務對應的服務器名稱和它的IP地址。
爲了讓用戶更容易發現本地網絡中的各種服務,Bonjour爲設備提供了服務發現的能力。
Bonjour提供的服務發現能力基於一個簡單直接的規定,就是提供服務的設備在按以下標準對服務進行註冊:名稱.服務類型.傳輸協議類型.local.”,比如:“DamonWebServer._http._tcp.local.”,又比如“DummiesWebServer._http._tcp.local.”
這樣,當一個設備使用希望查找http服務的時候,Bonjour會去查找本地網絡中註冊過的包含"_http"的服務,然後將結果返回給用戶選擇。這時用戶面對的是“DamonWebServer”"DummiesWebServer",用戶可以不去關心到底這兩個web服務到底在那臺設備上,該設備的IP地址是什麼。

3. 如何使用Bonjour
對於最終用戶來講,Bonjour基本上是透明的,他們不需要了解如何去使用Bonjour,往往都是應用開發者去考慮如何使用Bonjour
對於應用開發者來講,他們需要考慮有兩部分,一是如何作爲Bonjour客戶端去發現使用本地服務,二是如何作爲服務端如何註冊Bonjour服務

3.1 如何作爲Bonjour客戶端去發現本地服務
iOS開發可以使用NSNetService框架中的NSNetServiceBrowser類去發現本地服務。
基本過程如下:
首先創建NSNetServiceBrowser實例:

serviceBrowser = [[NSNetServiceBrowser allocinit];

然後指定NSNetServiceBrowser實例的代理,所指定的代理需要實現“NSNetServiceBrowserDelegate”協議。由實現以上協議的代理對服務查找相關的事件進行響應。這裏指定本實例爲NSNetServiceBrowser代理,由本例對服務查找的事件進行響應:

serviceBrowser.delegate = self;

接着使用NSNetServiceBrowser實例的searchForServicesOfType方法查找服務,方法中可以指定需要查找的服務類型和查找的域。以下樣例查找“local.”域中的“http”服務:

[serviceBrowser searchForServicesOfType:@"_http._tcp." inDomain:@"local."];

最後,在“NSNetServiceBrowserDelegate”的以下方法中響應“didFindService”事件,就是找到服務的事件。其中的netService參數就是找到的服務,在netService參數中可以得到服務地址,服務主機名等信息。

- (void)netServiceBrowser:(NSNetServiceBrowser *)netServiceBrowser didFindService:(NSNetService *)netService moreComing:(BOOL)moreServicesComing 
{



3.2 如何作爲服務端註冊Bonjour服務
要註冊成爲Bonjour服務,開發者可以直接創建NSNetService實例,並通過initwithDomain: type: name: port:方法進行初始化,指定服務的域,類型,名稱和端口,樣例代碼如下:

service = [[NSNetService allocinitWithDomain:@"local." type:@"_http._tcp." name:@"DamonWebServer" port:port];

NSNetService創建成功後,可以通過setDelegate指定代理,同時通過publish方法發佈註冊服務:

        

        [service setDelegate:self];
        [service publish];

     

其中指定的代理需要遵從“NSNetServiceDelegate”協議,可以對服務發佈成功,發佈失敗等事件。

正常來講,如果需要發佈一個服務,需要在發佈服務之前準備好服務並啓動它。不過NSNetService的publish方法並不依賴它所發佈的服務,不管服務是否準備好,是否啓動,NSNetService的publish都可以成功將服務發佈出去,只不過服務發佈出去後其它使用這個服務的客戶端會發現這個發佈出來的服務是個無效服務。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章