發(fā)現(xiàn)并公布網(wǎng)絡(luò)服務(wù) <- 網(wǎng)絡(luò)概述

OS X和iOS提供四個發(fā)現(xiàn)并公布網(wǎng)絡(luò)服務(wù)的API。

  • NSNetService —— 適合大多數(shù)應(yīng)用開發(fā)的高級OC API。
  • CFNetService —— 適合Core Fondation代碼的高級C API。
  • DNS Service Discovery —— 適合跨平臺的代碼的低級C API。
  • Game Kit 框架 —— 為游戲提供點對點通信的高級OC API,可在本地(使用藍牙和Wi-Fi)以及全球網(wǎng)絡(luò)環(huán)境下使用。

除了這些API之外,Multipeer Connectivity 框架也提供對安裝有同一款(或有相關(guān)性)應(yīng)用的臨近設(shè)備的相互發(fā)現(xiàn)和通信的支持。這些應(yīng)用的所在設(shè)備,使用了基礎(chǔ)Wi-Fi、點對點Wi-Fi、以及藍牙(對于iOS)或者以太網(wǎng)(對于OS X)。

作為規(guī)則,你應(yīng)該為游戲相關(guān)的點對點網(wǎng)絡(luò)只使用Game Kit。對于運行iOS 7及更高版本的iOS設(shè)備之間的點對點網(wǎng)絡(luò)。你應(yīng)該使用Multipeer Connectivity框架。

為了兼容舊版本的iOS,你也可以使用CFNetService 或 NSNetService 編寫自己的網(wǎng)絡(luò)代碼來進行發(fā)布。

注意:在支持藍牙的設(shè)備上,藍牙通訊通過Game Kit是自動使用的。(當(dāng)通過設(shè)置interfaceIndex為kDNSServiceFlagsIncludeP2P來使用DNS Service Discovery C API的時候,使用藍牙的Bonjour也可以被啟用。詳情見Bonjour over Bluetooth on iOS 5 and Later。)

Bonjour服務(wù)概述

Bonjour服務(wù)由三部分組成:

  • 服務(wù)名稱——這個名字對于在特定電腦上運行的特定應(yīng)用實例來說必須是唯一的。
  • 服務(wù)類型——它對于應(yīng)用的所有實例都必須是相同的,并且應(yīng)該向Internet Assigned Numbers Authority(互聯(lián)網(wǎng)號碼分配機構(gòu),IANA)注冊。
  • 域——如果域是空的,則主機會在它發(fā)布或瀏覽的域中進行選擇。

當(dāng)應(yīng)用瀏覽Bonjour服務(wù)的時候,它會請求與特定域的特定類型匹配的服務(wù),并且得到匹配的服務(wù)名字列表。然后,它會向用戶呈現(xiàn)合適的UI。當(dāng)用戶告訴應(yīng)用連接特定的服務(wù)時,應(yīng)用應(yīng)該使用連接到服務(wù)的(connect-to-service)API來進行連接。(如果因為某些原因無法這樣做,該應(yīng)用可以把服務(wù)的名字和端口傳遞給使用名字連接的(connect-by-name)API;如果通過名字連接的API不可用,該應(yīng)用可以請求Bonjour來解析主機名,然后該應(yīng)用可以通過IP地址和端口號來連接)。

發(fā)布網(wǎng)絡(luò)服務(wù)

Bonjour零配置網(wǎng)絡(luò)讓你可以在網(wǎng)絡(luò)上發(fā)布網(wǎng)絡(luò)服務(wù),例如打印機、或者文檔同步服務(wù)。這里有三種發(fā)布網(wǎng)絡(luò)服務(wù)的方式:

  • 對于OC和Core Foundation代碼,推薦的方式是使用CFNetServices API。
  • 對于必須可以運行在iOS 和 OS X以外操作系統(tǒng)上的可移植C代碼,推薦使用DNS Service Discovery C API。

你可以依照下面的步驟來發(fā)布網(wǎng)絡(luò)服務(wù):

  1. 創(chuàng)建一個socket來監(jiān)聽與服務(wù)器的連接。要了解監(jiān)聽網(wǎng)絡(luò)socket上的連接的推薦方式,請參閱Networking Programming Topics中的Writing a TCP-Based Server。
  2. 創(chuàng)建一個服務(wù)對象,提供你的socket端口、域(通常是空字符串)、以及你選擇的服務(wù)類型字符串:
  • 對于Foundation,使用initWithDomain:type:name:port:方法初始化NSNetService對象。
  • 對于Core Foundation,使用CFNetServiceCreate函數(shù)創(chuàng)建CFNetServiceRef對象。
  • 對于DNS Service Discovery API,,調(diào)用DNSServiceRegister來返回DNSServiceRef對象。
  1. 分配一個委托或回調(diào):
  • 對于Foundation,使用委托方法給NSNetService對象分配一個委托。
  • 對于Core Foundation,使用CFNetServiceSetClient函數(shù)給CFNetServiceRef對象分配一個委托人回調(diào)。
  • 對于DNS Service Discovery API,你應(yīng)該在調(diào)用DNSServiceRegister時傳遞一個委托人回調(diào)(或者,一個指向你選擇的上下文對象的指針)。此時,除了當(dāng)發(fā)生時處理回調(diào)的內(nèi)容,其他已經(jīng)完成。
  1. 如有需要,安排或重新安排服務(wù):
  • 對于Foundation,在默認(rèn)模式下,該服務(wù)會在當(dāng)前運行循環(huán)上被自動安排。如果你需要把該對象安排在另一個運行循環(huán)或不同的模式下,你應(yīng)該取消安排并重新安排。
  • 對于Core Foundation,你必須通過調(diào)用CFNetServiceScheduleWithRunLoop在運行循環(huán)上安排CFNetServicesRef對象。
  • 對于DNS Service Discovery API,調(diào)用DNSServiceSetDispatchQueue,在調(diào)度隊列上安排服務(wù)。(如果你必須支持OS X 10.7之前的操作系統(tǒng),參見SRVResolver樣例代碼,它是一個說明在沒有Grand Central Dispatch的情況下如何使用DNS Service Discovery的例子。)
  1. 如有必要,發(fā)布服務(wù):
  • 對于Foundation,通過調(diào)用publish方法發(fā)布服務(wù)。
  • 對于Core Foundation,通過調(diào)用CFNetServiceRegisterWithOptions發(fā)布服務(wù)。
  • 對于DNS Service Discovery API,不需要進一步操作;當(dāng)你調(diào)用DNSServiceRegister的時候,服務(wù)就已經(jīng)發(fā)布。

當(dāng)你的服務(wù)發(fā)布后,你可以監(jiān)聽socket上的連接,并在連接時設(shè)置輸入輸出流。

重要:如果你創(chuàng)建了一個自定義協(xié)議,你應(yīng)該使用自定義的服務(wù)類型,并使用IANA注冊這個服務(wù)類型。詳細信息,參見RFC 6335。

瀏覽和連接網(wǎng)絡(luò)服務(wù)

尋找和解析網(wǎng)絡(luò)服務(wù)的過程和發(fā)布它的過程一樣簡單。要在OC中瀏覽網(wǎng)絡(luò)服務(wù),創(chuàng)建一個NSNetServiceBrowser類的實例,并給它分配一個委托。然后該服務(wù)瀏覽器調(diào)用searchForServicesOfType:inDomain:方法。一旦有服務(wù)被發(fā)現(xiàn),netServiceBrowser:didFindService:moreComing:委托方法就會被調(diào)用。

想要連接服務(wù)器,首先通過調(diào)用stop來暫停瀏覽(除非你有特殊的原因要繼續(xù)瀏覽),然后用代表服務(wù)的NSNetService對象調(diào)用getInputStream:outputStream:方法。服務(wù)的地址將會自動解析。

你還可以使用帶有CFNetServiceRef對象的CFStreamCreatePairWithSocketToNetService方法,來連接Bonjour服務(wù)。

重要:如果你正在使用ARC,你應(yīng)該閱讀NSNetService and Automatic Reference Counting (ARC)。

解析網(wǎng)絡(luò)服務(wù)

你或許需要手動解析網(wǎng)絡(luò)服務(wù),以便提供服務(wù)的地址給沒有接收到網(wǎng)絡(luò)服務(wù)名稱的API。想要在OC中解析網(wǎng)絡(luò)服務(wù),首先通過調(diào)用stop來聽值瀏覽,然后該服務(wù)的NSNetService對象調(diào)用resolveWithTimeout:方法。

當(dāng)服務(wù)的地址被解析之后,會調(diào)用服務(wù)的委托中的netServiceDidResolveAddress:方法。然后你可以使用hostName方法訪問服務(wù)的主機名,或使用addresses方法訪問它的地址信息。為了避免不必要的網(wǎng)絡(luò)流量,你還應(yīng)該在得到一組地址返回后,讓NSNetService對象調(diào)用stop。

重要:這個解析過程返回數(shù)字的IP地址和主機名。IP地址可以是IPv4和IPv6地址的任意組合。除非你做不尋常的事,否則你通常應(yīng)該將主機名傳遞給任何支持主機名的API,而不是直接使用IP地址,否則,你將不得不編寫自己的代碼來嘗試將每個IP地址進行并聯(lián)或串聯(lián)(進一步描述在Avoid Resolving DNS Names Before Connecting to a Host中)。

多點連接(Multipeer Connectivity)概述

Multipeer Connectivity(多點連接)框架提供一個在Bonjour頂部的層,它讓你與附近設(shè)備(通過基礎(chǔ)Wi-Fi、點對點Wi-Fi、藍牙或以太網(wǎng))上運行的應(yīng)用通信,而無需為你的應(yīng)用編寫很多網(wǎng)絡(luò)代碼。

使用多點連接,應(yīng)用可以發(fā)布其可用性。然后,它可以發(fā)現(xiàn)正在附近其他設(shè)備上運行的該應(yīng)用(或共享同一個服務(wù)類型的其他應(yīng)用),并可以邀請這些附近的點加入會話。如果它們接收邀請,應(yīng)用就可以指通過一個方法調(diào)用發(fā)送信息或文本到一個或多個連接的點。

重要:與Bonjour一樣,應(yīng)用必須提供服務(wù)類型,并且你應(yīng)該使用IANA注冊服務(wù)類型,參見RFC 6335。

如果你需要基于流的通信,應(yīng)用可以打開單向流到任何連接的點(它也可以打開一個單向流返回到該應(yīng)用作為響應(yīng))。

最后,多點連接提供在會話上下文之外分享少量數(shù)據(jù)的能力,如果需要,允許你提供給用戶一些信息,用戶可以在選擇點時使用這些信息訪問會話。

了解更多

Multipeer Connectivity——閱讀Multipeer Connectivity Framework Reference和MultipeerGroupChat樣例代碼項目

Game Kit——閱讀Game Center Programming Guide, Game Kit Framework Reference,以及 GKRocket and GKTank樣例代碼項目

NSNetService—閱讀 NSNetServices and CFNetServices Programming Guide, NSNetServiceBrowser Class Reference, NSNetServiceBrowserDelegate Protocol Reference, 以及 NSNetServiceDelegate Protocol Reference. 樣例代碼, 參見RemoteCurrency 樣例代碼項目.

CFNetService—閱讀 NSNetServices and CFNetServices Programming Guide 和 CFNetServices Reference.

DNS Service Discovery—閱讀 DNS Service Discovery Programming Guide 和 DNS Service Discovery C Reference.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容