iOS 上的 WebSocket 框架 Starscream

iOS 上的 WebSocket 框架 Starscream


傳統(tǒng)的網(wǎng)絡(luò)技術(shù) (也就是 Berkeley sockets) 被認(rèn)為是可靠和穩(wěn)定的浦徊。但是 Berkeley socket 在某些 web 技術(shù),比如代理和防火墻下不太好使天梧。WebSocket 出現(xiàn)于 2011 年盔性,是一種在客戶端和服務(wù)端之間建立雙向通訊的新技術(shù)。WebSocket 比起多個 HTTP 請求來說更有效率并允許長連接呢岗。

在 iOS 上使用 WebSocket 并不是那么容易交洗。iOS 和 Mac 庫 Starscream 的出現(xiàn)汉形,極大地簡化了 WebSocket 的創(chuàng)建和使用枪汪。

注:本文假設(shè)你熟悉 CocoaPods怀愧。如果你不熟悉,請參考我們的?CocoaPods 教程挫酿。

在本文中构眯,你將在一個叫做 Emoji Commuicator 的 App 中完成網(wǎng)絡(luò)編程部分。Emoji Communicator 允許你將當(dāng)前心情用一個 emoji 字符發(fā)布給所有連接到該服務(wù)的人早龟。

Emoji Communicator 原來的開發(fā)者原本打算用 HTTP 請求獲取新消息惫霸,但這個功能使用 WebSocket 顯然更合適。你將使用 Starscream 來連接后臺的 Web 服務(wù)器葱弟。

開始

首先需要一個 Web 服務(wù)器壹店。在本文中,你會在本機上啟動一個 web 服務(wù)器芝加。這個示例的 web 服務(wù)器運行在 Node.js 下茫打,使用一小個 Javascript 文件來支持它。

當(dāng)然,首先需要安裝 Node.js老赤。如果不確定是否已經(jīng)安裝,可以在終端窗口中輸入命令:

node--version

1

如果報錯制市,請按照下列步驟下載和安裝 Node.js抬旺。否則,你會看到 Node.js 的版本號祥楣,你就可以跳過下一節(jié) Node.js 的下載开财。

安裝和下載 Node.js

在?https://nodejs.org/?下載 Node.js 的最新安裝包 (當(dāng)前 2016.9.22 的最新版本是)。下載完安裝包 (例如 node-v6.6.0.pkg)误褪,雙擊進行安裝责鳍。參考提示進行,選擇默認(rèn)選項就行了兽间。

安裝完后历葛,在終端中檢查 Node.js 是否工作正常:

node--version

1

如果你沒有看到 6.6.0 (或者你所安裝的版本),或者報錯嘀略,再次檢查安裝是否正確恤溶。

聊天服務(wù)器

你將用到一個聊天服務(wù)器。從這里下載示例 iOS app 和 Web 服務(wù)器代碼帜羊。解壓縮 zip 包到桌面或者某個文件夾咒程。在終端中,切換到該目錄讼育,并進入 nodeapp 子目錄帐姻。

這個程序需要一個第三方模塊,需要用 Node.js 的包管理器 npm 來安裝奶段。在這個目錄中饥瓷,執(zhí)行:

npminstallwebsocket

1

輸入下列命令啟動聊天服務(wù)器:

node chat-server.js

1

你會看到類似如下輸出:

Tue Sep13201618:54:44GMT-0500(CDT) Serverislisteningonport1337

1

然后在瀏覽器 Safari 或 Chrome 中打開 frontend.html。?

輸入一個昵稱忧饭,發(fā)送一條測試消息扛伍。如果要在第二個客戶端進行測試,重新打開一個瀏覽器或標(biāo)簽頁词裤,用同一個 Url刺洒。用另一個昵稱登錄,發(fā)送一條消息吼砂;你會看到消息立即出現(xiàn)在另一個瀏覽器里逆航。

這充分說明了 WebSocket 的強大之處。每個瀏覽器都和 web 服務(wù)器有一個單獨的長連接——沒有刷新渔肩。當(dāng)消息到達因俐,服務(wù)器會自動向所有連接著的客戶端進行廣播。返回終端,你可以看到所有的聊天活動:

$nodechat-server.jsTueSep13 2016 18:54:44GMT-0500(CDT)Serverislisteningonport1337TueSep13 2016 18:55:19GMT-0500(CDT)Connectionfromoriginnull.TueSep13 2016 18:55:19GMT-0500(CDT)Connectionaccepted.TueSep13 2016 18:55:34GMT-0500(CDT)Userisknownas:Aaronwithgreencolor.TueSep13 2016 18:55:37GMT-0500(CDT)ReceivedMessagefromAaron:HelloTueSep13 2016 18:58:49GMT-0500(CDT)Connectionfromoriginnull.TueSep13 2016 18:58:49GMT-0500(CDT)Connectionaccepted.TueSep13 2016 18:58:51GMT-0500(CDT)Userisknownas:Jameswithredcolor.TueSep13 2016 18:58:55GMT-0500(CDT)ReceivedMessagefromJames:Thisisprettyslick!TueSep13 2016 18:59:03GMT-0500(CDT)ReceivedMessagefromJames: :]TueSep13 2016 18:59:27GMT-0500(CDT)Peerundefineddisconnected.

WebSockets

HTTP 第一次出現(xiàn)是 1991 年抹剩,它設(shè)計為一種請求/響應(yīng)式的通訊機制撑帖。Web 瀏覽器用這種機制工作良好,用戶請求 web 頁澳眷,服務(wù)器返回內(nèi)容胡嘿。但某些時候,需要有新數(shù)據(jù)時不經(jīng)過用戶請求就通知用戶——也就是钳踊,服務(wù)器推衷敌。

HTTP 協(xié)議無法很好地解決推模型。在 websocket 出現(xiàn)前拓瞪,web 服務(wù)通過一系列瀏覽器刷新機制來實現(xiàn)推模型缴罗,但效率無法讓人滿意。

webSocket 實現(xiàn)了服務(wù)端推機制祭埂。新的 web 瀏覽器全都支持 WebSocket面氓,這使得它的使用超級簡單。通過 WebSocket 能夠打開持久連接沟堡,大部分網(wǎng)絡(luò)都能輕松處理 WebSocket 連接侧但。

WebSocket 通常應(yīng)用在某些數(shù)據(jù)經(jīng)常性或頻繁改變的場景。例如 Facebook 中的 web 通知航罗、Slack 中的實時聊天禀横、交易系統(tǒng)中的變化的股票價格。

在 iOS 中使用 WebSocket 比較麻煩粥血,你必須進行大量的設(shè)置柏锄,而且內(nèi)置的 API 根本幫不上忙。這時 Starscream 出現(xiàn)了——這個小巧复亏、易于使用的庫讓你所有的煩惱不翼而飛趾娃。

Emoji Communicator

打開 EmojiTransmitter.xcodeproj。在模擬器中運行程序缔御,程序很簡單抬闷,它需要用戶輸入一個昵稱,然后顯示一個界面耕突,讓用戶選擇一個 emoji 發(fā)送笤成,并顯示任何接收到的 emoji。

這個 App 還沒有完成網(wǎng)絡(luò)部分眷茁。你將使用 Starscream 來執(zhí)行所有的 WebSocket 網(wǎng)絡(luò)請求炕泳。

有許多方法可以將 Starscream 集成到你的項目。CocoaPods 和 Carthage 是兩種最常見的包管理器上祈。你兩種都可以用培遵,但本文將使用 CocoaPods浙芙。

首先,關(guān)閉打開的項目籽腕。開啟終端窗口嗡呼,將目錄切換至項目文件夾。在這個項目中已經(jīng)有一個配置了 Starscream pod 的 Podfile 文件了节仿。你可以直接安裝 pod:

pod repoupdate;pod install

1

當(dāng) CocoaPods 結(jié)束安裝晤锥,在 Xcode 8 中打開 EmojiTransmitter.xcworkspace 文件。運行程序廊宪,檢查 App 是否能夠運行。?

打開 ViewController.swift女轿,在 import UIKit 后加入:

importStarscream

1

然后箭启,在 ViewController 類的 username 屬性后增加一個屬性:

varsocket= WebSocket(url:URL(string:"ws://localhost:1337/")!, protocols: ["chat"])

1

這是創(chuàng)建 WebSocket 連接的核心。注意 URL 的歌聲蛉迹,協(xié)議是 ws 而不是 Http/https傅寡。protocols 參數(shù)指定為 chat,這取決于服務(wù)端的實現(xiàn)北救,這個協(xié)議可以被使用荐操,也可能被忽略。在本 demo 中珍策,忽略它即可托启。?

接著在 viewDidLoad 方法后加入:

deinit {socket.disconnect(forceTimeout:0)socket.delegate = nil}

1

2

3

4

當(dāng) View Controller 被銷毀時,強制關(guān)閉 WebSocket 連接攘宙。

在 Starscream 中所有的工作都放在 delegate 中進行屯耸。Starscream 也支持閉包,如果你不愿意使用委托的話蹭劈。

在 ViewController.swift疗绣,在 fileprivate 擴展后增加一個擴展:

// MARK: - WebSocketDelegateextension ViewController : WebSocketDelegate {publicfuncwebsocketDidConnect(_ socket: Starscream.WebSocket) {? }publicfuncwebsocketDidDisconnect(_ socket: Starscream.WebSocket, error: NSError?) {? }publicfuncwebsocketDidReceiveMessage(_ socket: Starscream.WebSocket, text: String) {? }publicfuncwebsocketDidReceiveData(_ socket: Starscream.WebSocket, data: Data) {? }}


這 4 個委托方法必須實現(xiàn),否則代碼無法通過編譯铺韧。

然后多矮,在 viewDidLoad 方法的 super.viewDidLoad() 后面添加:

socket.delegate = selfsocket.connect()


運行程序,輸入昵稱哈打,點擊 Next塔逃。返回 Node.js 控制臺你將看到有一個連接通知。

現(xiàn)在前酿,你已經(jīng)能夠連接到 Node.js App 了患雏,接下來是發(fā)送消息到服務(wù)器。

首先罢维,將 sendMessage(_:) 方法修改為:

func sendMessage(_message:String) {? socket.write(string:message)}


這會發(fā)送消息(本例中淹仑,就是 emoji)到 Node.js 服務(wù)器丙挽。

然后,在 websocketDidConnect(_:) 方法中加入:

socket.write(string: username)

1

這會在連接建立后發(fā)送你在第一個界面中輸入的昵稱匀借。這個服務(wù)器會將第一個接收到的消息當(dāng)做用戶名稱颜阐。?

在 websocketDidDisconnect(_:error:) 中加入:

performSegue(withIdentifier:"websocketDisconnected", sender: self)

1

無論什么原因,只要 socket 被斷開吓肋,這都會讓用戶返回到輸入昵稱界面凳怨。如果在你自己的 App 中,你應(yīng)當(dāng)在這里進行更健全的錯誤處理是鬼。

接著肤舞,在 websocketDidReceiveMessage(_:text:) 方法中:

// 1guardletdata = text.data(using: .utf16),letjsonData =try? JSONSerialization.jsonObject(with: data),letjsonDict = jsonDataas? [String: Any],letmessageType = jsonDict["type"]as? Stringelse{return}// 2ifmessageType =="message",letmessageData = jsonDict["data"]as? [String: Any],letmessageAuthor = messageData["author"]as? String,letmessageText = messageData["text"]as? String {? messageReceived(messageText, senderName: messageAuthor)}


收到的文字消息是可讀的字符串——如果是 JSON,嘗試將其轉(zhuǎn)為集合對象均蜜。代碼解釋如下:

首先將字符串轉(zhuǎn)為 NSData李剖,然后將 NSData 傳給 JSONSerialization 對象以將其轉(zhuǎn)為載體并返回一個有效的對象。最后還檢查了幾個重要的 key囤耳,并設(shè)置對應(yīng)的值篙顺。如果對象無效,直接通過 guard 語句退出充择。

過濾消息的 messageType德玫,然后將數(shù)據(jù)傳遞給 messageReceived(messageText:, senderName:) 方法。

下面是一個從 Node.js 收到的 JSON 格式的消息示例:

{? "type":"message",? "data":{? ? "time":1472513071731,? ? "text":":]",? ? "author":"iPhone Simulator",? ? "color":"orange"}}


運行 app椎麦,每當(dāng)你發(fā)送一條消息宰僧,emoji 將會用你選擇的 emoji 和昵稱刷新。返回 web 控制臺铃剔,你的 emoji 消息也會顯示撒桨。

這就是 Starscream 的使用!

結(jié)束

這里下載最終完成的項目键兜。

Emoji Communicator 是一個使用 WebSocket 的最簡單的例子凤类。如果你想在已經(jīng)存在的服務(wù)中使用 Starscream,你可以參考更多資料:

參考?Starscream 在 GitHub 上的項目主頁?普气。

參考?Mozilla 開發(fā)者網(wǎng)絡(luò)?上關(guān)于 WebSocket 的介紹和如何實現(xiàn) WebSocket谜疤。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市现诀,隨后出現(xiàn)的幾起案子夷磕,更是在濱河造成了極大的恐慌,老刑警劉巖仔沿,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坐桩,死亡現(xiàn)場離奇詭異,居然都是意外死亡封锉,警方通過查閱死者的電腦和手機绵跷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門膘螟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人碾局,你說我怎么就攤上這事荆残。” “怎么了净当?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵内斯,是天一觀的道長。 經(jīng)常有香客問我像啼,道長俘闯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任忽冻,我火速辦了婚禮备徐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘甚颂。我一直安慰自己,他們只是感情好秀菱,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布振诬。 她就那樣靜靜地躺著,像睡著了一般衍菱。 火紅的嫁衣襯著肌膚如雪赶么。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天脊串,我揣著相機與錄音辫呻,去河邊找鬼。 笑死琼锋,一個胖子當(dāng)著我的面吹牛放闺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缕坎,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼怖侦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谜叹?” 一聲冷哼從身側(cè)響起匾寝,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎荷腊,沒想到半個月后艳悔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡女仰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年猜年,在試婚紗的時候發(fā)現(xiàn)自己被綠了抡锈。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡码倦,死狀恐怖企孩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情袁稽,我是刑警寧澤勿璃,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站推汽,受9級特大地震影響补疑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜歹撒,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一莲组、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧暖夭,春花似錦锹杈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至裕菠,卻和暖如春咬清,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背奴潘。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工旧烧, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人画髓。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓掘剪,卻偏偏與公主長得像,于是被迫代替她去往敵國和親雀扶。 傳聞我的和親對象是個殘疾皇子杖小,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

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