iOS Bonjour的使用-本地通信/智能交互

原文鏈接: http://fighting300.com...

之前一直考慮在local現(xiàn)場怎么與別的用戶通信,后來陸續(xù)了解了蘋果的Bonjour×勺埃現(xiàn)在簡單寫一篇Bonjour的入門介紹。

Bonjour介紹

bonjour其實來自法語透葛,是你好的意思续镇。而Bonjour服務是蘋果公司發(fā)布的一個基于ZEROCONF工作組(IETF下屬小組)的工作,用于實現(xiàn)零配置網(wǎng)絡聯(lián)網(wǎng)的解決方案。Bonjour是基于IP層協(xié)議的,簡單來說,就是一套解決方案,能夠不需要復雜的配置,即可互相發(fā)現(xiàn)彼此的解決方案陵究∶咭可以用它來輕松探測并連接到相同網(wǎng)絡中的其他設備,并與別的智能硬件進行交互或者其他操作铜邮。典型的Bonjour應用有Remote仪召、AirPrint等寨蹋。

Bonjour-overview

為了實現(xiàn)簡單配置網(wǎng)絡,Bonjour做了以下三點:

  1. 尋址(分配IP地址給主機)
    一個在網(wǎng)絡中的設備需要有一個自己的IP扔茅。有了IP地址,我們才能基于IP協(xié)議進行通信已旧。對于IPV6標準,IP協(xié)議已經(jīng)包括了自動尋找IP地址的功能。但是目前仍然普遍使用的IPV4不包含本地鏈路尋址功能召娜。而Bonjour會在本地網(wǎng)絡選擇一個隨機的IP地址進行測試,如果已經(jīng)被占用,則繼續(xù)挑選另外一個地址运褪,直到選到可用的IP地址。

  2. 命名(使用名字而不是IP地址來代表主機)
    Bonjour還實現(xiàn)了命名和解析功能玖瘸,保證了我們服務的名字在本地網(wǎng)絡是唯一的,并且把別人對我們名字的查詢指向正確的IP地址和端口秸讹,而不是以IP地址這樣不易讀的方式來作為服務的標志。
    而且Bonjour在系統(tǒng)級別上添加了一個mDNSResponder服務來處理請求和發(fā)送回復,從系統(tǒng)級層面上處理,我們就無需在應用內(nèi)自己監(jiān)聽和返回IP地址,只需到系統(tǒng)內(nèi)注冊服務即可雅倒。減少了我們應用的工作量和提高了穩(wěn)定性璃诀。

  3. 服務搜索(自動在網(wǎng)絡搜索服務)
    Bonjour可以只需指定所需服務的類型,即可收到本地網(wǎng)絡上可用的設備列表蔑匣。設備在本地網(wǎng)絡發(fā)出請求,說我需要"XXX"類型的服務,例如:我要打印機服務文虏。所有打印機服務的設備回應自己的名字。

Bonjour API

Cocoa中網(wǎng)絡框架有三層殖演,最底層的是基于 BSD socket庫氧秘,然后是 Cocoa 中基于 C 的 CFNetwork,最上面一層是 Cocoa 中 Bonjour趴久。通常我們無需與 socket 打交道丸相,我們會使用經(jīng) Cocoa 封裝的 CFNetwork 和 Bonjour 來完成大多數(shù)工作。

cocoa 很多組件都有兩種實現(xiàn)彼棍,一種是基于 C 的以 CF 開頭的類(CF=Core Foundation)灭忠,這是比較底層的;另一種是基于 Obj-C 的以 NS 開頭的類(NS=Next Step)座硕,這種類抽象層次更高弛作,易于使用。對于網(wǎng)絡框架也一樣华匾。Bonjour 中 NSNetService 也有對應的 CFNetService映琳,NSInputStream 有對應的 CFInputStream。

通過 Bonjour蜘拉,一個應用程序publish一個網(wǎng)絡服務 service萨西,然后網(wǎng)絡中的其他程序就能自動發(fā)現(xiàn)這個 service,從而可以向這個 service 查詢其 ip 和 port旭旭,然后通過獲得的 ip 和 port 建立 socket 鏈接進行通信谎脯。通常我們是通過 NSNetService 和 NSNetServiceBrowser 來使用 Bonjour 的,前者用于建立與發(fā)布 service持寄,后者用于監(jiān)聽查詢網(wǎng)絡上的 service源梭。

Bonjour-API

建立連接

簡單來說娱俺,建立Bonjour連接一般需要三個步驟,即服務端發(fā)布服務废麻、客戶端瀏覽服務矢否、客戶端/服務端交互。

Bonjour-API
客戶端發(fā)布服務

首先通過NetService對象初始化服務脑溢,指定服務的域僵朗、類型、名稱和端口屑彻,在同一網(wǎng)絡中验庙,服務類型名必須唯一,這樣才能精準定位服務社牲。
Bonjour操作也需要異步進行粪薛,以免長時間阻礙主線程,所以我們將發(fā)布任務交給當前run loop去調(diào)度搏恤。

    func setupService(){
        let service = NetService.init(domain: "local.", type: "_dragon._tcp", name: "dragon", port: 2333)
        service.schedule(in: RunLoop.current, forMode: .commonModes)
        service.delegate = self
        let dictData = "http://fighting300.github.io".data(using: String.Encoding.utf8)
        let data = NetService.data(fromTXTRecord: ["node":dictData!])
        service.setTXTRecord(data)
        service.publish()
        self.service = service
    }

另外需要實現(xiàn)NetService協(xié)議NetServiceDelegate的代理方法跟蹤服務發(fā)布信息违寿。

  func netServiceWillPublish(_ sender: NetService) {
      print("----netServiceWillPublish")
  }
  func netService(_ sender: NetService, didNotPublish errorDict: [String : NSNumber]) {
      print("----netService didNotPublish")
  }

客戶端瀏覽服務

服務發(fā)布成功后,會在代理方法中接受到發(fā)布的消息熟空,這時候要在客戶端通過NetServiceBrowser對象來瀏覽本地的服務藤巢,并展示本地網(wǎng)絡中可用的服務。
可以通過searchForServices方法指定需要查找的服務類型和查找的域息罗,然后運行在mainRunLoop中掂咒。

    func netServiceDidPublish(_ sender: NetService) {
        print("----netService didPublish")
        let browser = NetServiceBrowser()
        browser.delegate = self
        browser.searchForServices(ofType: "_WE._tcp", inDomain: "local.")
        browser.schedule(in: RunLoop.current, forMode: .commonModes)
        RunLoop.current.run(until: Date.init(timeIntervalSinceNow: 300))
    }

同時實現(xiàn)NetServiceBrowser的代理NetServiceBrowserDelegate方法netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool)來處理相應服務的解析。當前代碼實例中沒有選擇服務的服務迈喉,直接對掃描到的服務來做解析。

    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
        print("----netServiceBrowser didFind", service.domain, service.type, service.name, service.port,service)
        // 在界面選擇對應的service
        self.service = service
        service.delegate = self
        service.resolve(withTimeout: 5)
    }

    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
        print("----netServiceBrowser didRemove")
    }
客戶端/服務端交互

最后挨摸,可以在NetService代理的解析方法里func netServiceDidResolveAddress(_ sender: NetService),拿到名稱得运、類型、域澈圈、主機名和ip地址等信息彬檀。

    func netServiceWillResolve(_ sender: NetService) {
        print("----netService willResolve")
    }

    func netServiceDidResolveAddress(_ sender: NetService) {
        print("----netService didResolveAddress", sender.name, sender.addresses, sender.hostName, sender.addresses?.first)
        let data = sender.txtRecordData()
        let dict = NetService.dictionary(fromTXTRecord: data!)
        let info = String.init(data: dict["node"]!, encoding: String.Encoding.utf8)
        print("mac info = ",info);

    }

    func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) {
        print("----netService didNotResolve ", errorDict)
    }

    func netServiceDidStop(_ sender: NetService) {
        print("----netServiceDidStop")
    }

    func netService(_ sender: NetService, didUpdateTXTRecord data: Data) {
        print("----netService didUpdateTXTRecord")
    }

    func netService(_ sender: NetService, didAcceptConnectionWith inputStream: InputStream, outputStream: OutputStream) {
        print("----netService didAcceptConnectionWith")
    }

    // MARK: util
    func IPFrom(data: Data) -> String {

        return ""
    }

之后依靠以上獲取的信息,需要通過Socket/Streams建立連接來進行通信努潘,本篇文章不對這部分做更多的介紹坤学,后續(xù)有時間再補充完整。

參考文檔
  1. http://mobileorchard.com/tutorial-networking-and-bonjour-on-iphone/
  2. https://developer.apple.com/library/content/documentation/Networking/Conceptual/NSNetServiceProgGuide/Introduction.html#//apple_ref/doc/uid/TP40002520-SW2
  3. http://www.cocoachina.com/ios/20150918/13434.html
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末深浮,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子飞苇,更是在濱河造成了極大的恐慌,老刑警劉巖蜗顽,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件橱鹏,死亡現(xiàn)場離奇詭異混狠,居然都是意外死亡,警方通過查閱死者的電腦和手機咽瓷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進店門崔挖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贸街,“玉大人,你說我怎么就攤上這事狸相⊙Ψ耍” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵脓鹃,是天一觀的道長蛋辈。 經(jīng)常有香客問我,道長将谊,這世上最難降的妖魔是什么冷溶? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮尊浓,結(jié)果婚禮上逞频,老公的妹妹穿的比我還像新娘。我一直安慰自己栋齿,他們只是感情好苗胀,可當我...
    茶點故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瓦堵,像睡著了一般基协。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上菇用,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天澜驮,我揣著相機與錄音,去河邊找鬼惋鸥。 笑死杂穷,一個胖子當著我的面吹牛悍缠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播耐量,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼飞蚓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了廊蜒?” 一聲冷哼從身側(cè)響起趴拧,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎山叮,沒想到半個月后著榴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡聘芜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年兄渺,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汰现。...
    茶點故事閱讀 39,696評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖口叙,靈堂內(nèi)的尸體忽然破棺而出嗅战,到底是詐尸還是另有隱情,我是刑警寧澤疟呐,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布启具,位于F島的核電站珊泳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏薯演。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一跨扮、第九天 我趴在偏房一處隱蔽的房頂上張望好港。 院中可真熱鬧米罚,春花似錦、人聲如沸拔莱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尊剔。三九已至菱皆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間京痢,已是汗流浹背篷店。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工疲陕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蹄殃。 一個月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓窃爷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親医吊。 傳聞我的和親對象是個殘疾皇子逮京,可洞房花燭夜當晚...
    茶點故事閱讀 44,592評論 2 353

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)览绿,斷路器,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,072評論 25 707
  • 名詞延伸 通俗的說,域名就相當于一個家庭的門牌號碼硕蛹,別人通過這個號碼可以很容易的找到你。如果把IP地址比作一間房子...
    楊大蝦閱讀 20,600評論 2 57
  • 如果你進來了,點下關(guān)注行不行_在使用這個bonjour協(xié)議之前, 先談談兩個問題? bonjour是什么?## b...
    travin閱讀 6,585評論 3 8
  • 關(guān)于大學 記得今年臨近開學的日子,爸爸說“終于大三了”鲤孵,我緩緩神,哦贵试,是哦,大三了凯正,若不是爸爸提起,完全意識不到...
    峰丫頭zheng閱讀 175評論 0 0