OS X和iOS提供四個(gè)發(fā)現(xiàn)并公布網(wǎng)絡(luò)服務(wù)的API。
- NSNetService —— 適合大多數(shù)應(yīng)用開發(fā)的高級(jí)OC API睁枕。
- CFNetService —— 適合Core Fondation代碼的高級(jí)C API斋荞。
- DNS Service Discovery —— 適合跨平臺(tái)的代碼的低級(jí)C API。
- Game Kit 框架 —— 為游戲提供點(diǎn)對(duì)點(diǎn)通信的高級(jí)OC API柱恤,可在本地(使用藍(lán)牙和Wi-Fi)以及全球網(wǎng)絡(luò)環(huán)境下使用宅广。
除了這些API之外,Multipeer Connectivity 框架也提供對(duì)安裝有同一款(或有相關(guān)性)應(yīng)用的臨近設(shè)備的相互發(fā)現(xiàn)和通信的支持。這些應(yīng)用的所在設(shè)備,使用了基礎(chǔ)Wi-Fi、點(diǎn)對(duì)點(diǎn)Wi-Fi捐晶、以及藍(lán)牙(對(duì)于iOS)或者以太網(wǎng)(對(duì)于OS X)。
作為規(guī)則妄辩,你應(yīng)該為游戲相關(guān)的點(diǎn)對(duì)點(diǎn)網(wǎng)絡(luò)只使用Game Kit惑灵。對(duì)于運(yùn)行iOS 7及更高版本的iOS設(shè)備之間的點(diǎn)對(duì)點(diǎn)網(wǎng)絡(luò)。你應(yīng)該使用Multipeer Connectivity框架眼耀。
為了兼容舊版本的iOS英支,你也可以使用CFNetService 或 NSNetService 編寫自己的網(wǎng)絡(luò)代碼來(lái)進(jìn)行發(fā)布。
注意:在支持藍(lán)牙的設(shè)備上哮伟,藍(lán)牙通訊通過(guò)Game Kit是自動(dòng)使用的干花。(當(dāng)通過(guò)設(shè)置interfaceIndex為kDNSServiceFlagsIncludeP2P來(lái)使用DNS Service Discovery C API的時(shí)候,使用藍(lán)牙的Bonjour也可以被啟用楞黄。詳情見Bonjour over Bluetooth on iOS 5 and Later池凄。)
Bonjour服務(wù)概述
Bonjour服務(wù)由三部分組成:
- 服務(wù)名稱——這個(gè)名字對(duì)于在特定電腦上運(yùn)行的特定應(yīng)用實(shí)例來(lái)說(shuō)必須是唯一的。
- 服務(wù)類型——它對(duì)于應(yīng)用的所有實(shí)例都必須是相同的鬼廓,并且應(yīng)該向Internet Assigned Numbers Authority(互聯(lián)網(wǎng)號(hào)碼分配機(jī)構(gòu)肿仑,IANA)注冊(cè)。
- 域——如果域是空的桑阶,則主機(jī)會(huì)在它發(fā)布或?yàn)g覽的域中進(jìn)行選擇柏副。
當(dāng)應(yīng)用瀏覽Bonjour服務(wù)的時(shí)候勾邦,它會(huì)請(qǐng)求與特定域的特定類型匹配的服務(wù)蚣录,并且得到匹配的服務(wù)名字列表。然后眷篇,它會(huì)向用戶呈現(xiàn)合適的UI萎河。當(dāng)用戶告訴應(yīng)用連接特定的服務(wù)時(shí),應(yīng)用應(yīng)該使用連接到服務(wù)的(connect-to-service)API來(lái)進(jìn)行連接蕉饼。(如果因?yàn)槟承┰驘o(wú)法這樣做虐杯,該應(yīng)用可以把服務(wù)的名字和端口傳遞給使用名字連接的(connect-by-name)API;如果通過(guò)名字連接的API不可用昧港,該應(yīng)用可以請(qǐng)求Bonjour來(lái)解析主機(jī)名擎椰,然后該應(yīng)用可以通過(guò)IP地址和端口號(hào)來(lái)連接)。
發(fā)布網(wǎng)絡(luò)服務(wù)
Bonjour零配置網(wǎng)絡(luò)讓你可以在網(wǎng)絡(luò)上發(fā)布網(wǎng)絡(luò)服務(wù)创肥,例如打印機(jī)达舒、或者文檔同步服務(wù)值朋。這里有三種發(fā)布網(wǎng)絡(luò)服務(wù)的方式:
- 對(duì)于OC和Core Foundation代碼,推薦的方式是使用CFNetServices API巩搏。
- 對(duì)于必須可以運(yùn)行在iOS 和 OS X以外操作系統(tǒng)上的可移植C代碼昨登,推薦使用DNS Service Discovery C API。
你可以依照下面的步驟來(lái)發(fā)布網(wǎng)絡(luò)服務(wù):
- 創(chuàng)建一個(gè)socket來(lái)監(jiān)聽與服務(wù)器的連接贯底。要了解監(jiān)聽網(wǎng)絡(luò)socket上的連接的推薦方式丰辣,請(qǐng)參閱Networking Programming Topics中的Writing a TCP-Based Server。
- 創(chuàng)建一個(gè)服務(wù)對(duì)象禽捆,提供你的socket端口笙什、域(通常是空字符串)、以及你選擇的服務(wù)類型字符串:
- 對(duì)于Foundation胚想,使用initWithDomain:type:name:port:方法初始化NSNetService對(duì)象得湘。
- 對(duì)于Core Foundation,使用CFNetServiceCreate函數(shù)創(chuàng)建CFNetServiceRef對(duì)象顿仇。
- 對(duì)于DNS Service Discovery API,淘正,調(diào)用DNSServiceRegister來(lái)返回DNSServiceRef對(duì)象。
- 分配一個(gè)委托或回調(diào):
- 對(duì)于Foundation臼闻,使用委托方法給NSNetService對(duì)象分配一個(gè)委托鸿吆。
- 對(duì)于Core Foundation,使用CFNetServiceSetClient函數(shù)給CFNetServiceRef對(duì)象分配一個(gè)委托人回調(diào)述呐。
- 對(duì)于DNS Service Discovery API惩淳,你應(yīng)該在調(diào)用DNSServiceRegister時(shí)傳遞一個(gè)委托人回調(diào)(或者,一個(gè)指向你選擇的上下文對(duì)象的指針)乓搬。此時(shí)思犁,除了當(dāng)發(fā)生時(shí)處理回調(diào)的內(nèi)容,其他已經(jīng)完成进肯。
- 如有需要激蹲,安排或重新安排服務(wù):
- 對(duì)于Foundation,在默認(rèn)模式下江掩,該服務(wù)會(huì)在當(dāng)前運(yùn)行循環(huán)上被自動(dòng)安排学辱。如果你需要把該對(duì)象安排在另一個(gè)運(yùn)行循環(huán)或不同的模式下,你應(yīng)該取消安排并重新安排环形。
- 對(duì)于Core Foundation策泣,你必須通過(guò)調(diào)用CFNetServiceScheduleWithRunLoop在運(yùn)行循環(huán)上安排CFNetServicesRef對(duì)象。
- 對(duì)于DNS Service Discovery API抬吟,調(diào)用DNSServiceSetDispatchQueue萨咕,在調(diào)度隊(duì)列上安排服務(wù)。(如果你必須支持OS X 10.7之前的操作系統(tǒng)火本,參見SRVResolver樣例代碼危队,它是一個(gè)說(shuō)明在沒(méi)有Grand Central Dispatch的情況下如何使用DNS Service Discovery的例子蓄喇。)
- 如有必要,發(fā)布服務(wù):
- 對(duì)于Foundation交掏,通過(guò)調(diào)用publish方法發(fā)布服務(wù)妆偏。
- 對(duì)于Core Foundation,通過(guò)調(diào)用CFNetServiceRegisterWithOptions發(fā)布服務(wù)盅弛。
- 對(duì)于DNS Service Discovery API钱骂,不需要進(jìn)一步操作;當(dāng)你調(diào)用DNSServiceRegister的時(shí)候挪鹏,服務(wù)就已經(jīng)發(fā)布见秽。
當(dāng)你的服務(wù)發(fā)布后,你可以監(jiān)聽socket上的連接讨盒,并在連接時(shí)設(shè)置輸入輸出流解取。
重要:如果你創(chuàng)建了一個(gè)自定義協(xié)議,你應(yīng)該使用自定義的服務(wù)類型返顺,并使用IANA注冊(cè)這個(gè)服務(wù)類型禀苦。詳細(xì)信息,參見RFC 6335遂鹊。
瀏覽和連接網(wǎng)絡(luò)服務(wù)
尋找和解析網(wǎng)絡(luò)服務(wù)的過(guò)程和發(fā)布它的過(guò)程一樣簡(jiǎn)單振乏。要在OC中瀏覽網(wǎng)絡(luò)服務(wù),創(chuàng)建一個(gè)NSNetServiceBrowser類的實(shí)例秉扑,并給它分配一個(gè)委托慧邮。然后該服務(wù)瀏覽器調(diào)用searchForServicesOfType:inDomain:方法。一旦有服務(wù)被發(fā)現(xiàn)舟陆,netServiceBrowser:didFindService:moreComing:委托方法就會(huì)被調(diào)用误澳。
想要連接服務(wù)器,首先通過(guò)調(diào)用stop來(lái)暫停瀏覽(除非你有特殊的原因要繼續(xù)瀏覽)秦躯,然后用代表服務(wù)的NSNetService對(duì)象調(diào)用getInputStream:outputStream:方法忆谓。服務(wù)的地址將會(huì)自動(dòng)解析。
你還可以使用帶有CFNetServiceRef對(duì)象的CFStreamCreatePairWithSocketToNetService方法宦赠,來(lái)連接Bonjour服務(wù)陪毡。
重要:如果你正在使用ARC米母,你應(yīng)該閱讀NSNetService and Automatic Reference Counting (ARC)勾扭。
解析網(wǎng)絡(luò)服務(wù)
你或許需要手動(dòng)解析網(wǎng)絡(luò)服務(wù),以便提供服務(wù)的地址給沒(méi)有接收到網(wǎng)絡(luò)服務(wù)名稱的API铁瞒。想要在OC中解析網(wǎng)絡(luò)服務(wù)妙色,首先通過(guò)調(diào)用stop來(lái)聽值瀏覽,然后該服務(wù)的NSNetService對(duì)象調(diào)用resolveWithTimeout:方法慧耍。
當(dāng)服務(wù)的地址被解析之后身辨,會(huì)調(diào)用服務(wù)的委托中的netServiceDidResolveAddress:方法丐谋。然后你可以使用hostName方法訪問(wèn)服務(wù)的主機(jī)名,或使用addresses方法訪問(wèn)它的地址信息煌珊。為了避免不必要的網(wǎng)絡(luò)流量号俐,你還應(yīng)該在得到一組地址返回后,讓NSNetService對(duì)象調(diào)用stop定庵。
重要:這個(gè)解析過(guò)程返回?cái)?shù)字的IP地址和主機(jī)名吏饿。IP地址可以是IPv4和IPv6地址的任意組合。除非你做不尋常的事蔬浙,否則你通常應(yīng)該將主機(jī)名傳遞給任何支持主機(jī)名的API猪落,而不是直接使用IP地址,否則畴博,你將不得不編寫自己的代碼來(lái)嘗試將每個(gè)IP地址進(jìn)行并聯(lián)或串聯(lián)(進(jìn)一步描述在Avoid Resolving DNS Names Before Connecting to a Host中)笨忌。
多點(diǎn)連接(Multipeer Connectivity)概述
Multipeer Connectivity(多點(diǎn)連接)框架提供一個(gè)在Bonjour頂部的層,它讓你與附近設(shè)備(通過(guò)基礎(chǔ)Wi-Fi俱病、點(diǎn)對(duì)點(diǎn)Wi-Fi官疲、藍(lán)牙或以太網(wǎng))上運(yùn)行的應(yīng)用通信,而無(wú)需為你的應(yīng)用編寫很多網(wǎng)絡(luò)代碼亮隙。
使用多點(diǎn)連接袁余,應(yīng)用可以發(fā)布其可用性。然后咱揍,它可以發(fā)現(xiàn)正在附近其他設(shè)備上運(yùn)行的該應(yīng)用(或共享同一個(gè)服務(wù)類型的其他應(yīng)用)颖榜,并可以邀請(qǐng)這些附近的點(diǎn)加入會(huì)話。如果它們接收邀請(qǐng)煤裙,應(yīng)用就可以指通過(guò)一個(gè)方法調(diào)用發(fā)送信息或文本到一個(gè)或多個(gè)連接的點(diǎn)掩完。
重要:與Bonjour一樣,應(yīng)用必須提供服務(wù)類型硼砰,并且你應(yīng)該使用IANA注冊(cè)服務(wù)類型且蓬,參見RFC 6335。
如果你需要基于流的通信题翰,應(yīng)用可以打開單向流到任何連接的點(diǎn)(它也可以打開一個(gè)單向流返回到該應(yīng)用作為響應(yīng))恶阴。
最后,多點(diǎn)連接提供在會(huì)話上下文之外分享少量數(shù)據(jù)的能力豹障,如果需要冯事,允許你提供給用戶一些信息,用戶可以在選擇點(diǎn)時(shí)使用這些信息訪問(wèn)會(huì)話血公。
了解更多
Multipeer Connectivity——閱讀Multipeer Connectivity Framework Reference和MultipeerGroupChat樣例代碼項(xiàng)目
Game Kit——閱讀Game Center Programming Guide, Game Kit Framework Reference昵仅,以及 GKRocket and GKTank樣例代碼項(xiàng)目
NSNetService—閱讀 NSNetServices and CFNetServices Programming Guide, NSNetServiceBrowser Class Reference, NSNetServiceBrowserDelegate Protocol Reference, 以及 NSNetServiceDelegate Protocol Reference. 樣例代碼, 參見RemoteCurrency 樣例代碼項(xiàng)目.
CFNetService—閱讀 NSNetServices and CFNetServices Programming Guide 和 CFNetServices Reference.
DNS Service Discovery—閱讀 DNS Service Discovery Programming Guide 和 DNS Service Discovery C Reference.