IOS之WebSocket框架Starscream案例詳解

傳統的網絡技術 (也就是 Berkeley sockets) 被認為是可靠和穩定的。但是 Berkeley socket 在某些 web 技術,比如代理和防火墻下不太好使。WebSocket 出現於 2011 年,是一種在客戶端和服務端之間建立雙向通訊的新技術。WebSocket 比起多個 HTTP 請求來說更有效率並允許長連接。

在 iOS 上使用 WebSocket 並不是那麼容易。iOS 和 Mac 庫 Starscream 的出現,極大地簡化瞭 WebSocket 的創建和使用。

註:本文假設你熟悉 CocoaPods。如果你不熟悉,請參考我們的 CocoaPods 教程。

在本文中,你將在一個叫做 Emoji Commuicator 的 App 中完成網絡編程部分。Emoji Communicator 允許你將當前心情用一個 emoji 字符發佈給所有連接到該服務的人。

Emoji Communicator 原來的開發者原本打算用 HTTP 請求獲取新消息,但這個功能使用 WebSocket 顯然更合適。你將使用 Starscream 來連接後臺的 Web 服務器。

開始

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

當然,首先需要安裝 Node.js。如果不確定是否已經安裝,可以在終端窗口中輸入命令:

node --version

如果報錯,請按照下列步驟下載和安裝 Node.js。否則,你會看到 Node.js 的版本號,你就可以跳過下一節 Node.js 的下載。

安裝和下載 Node.js

在 https://nodejs.org/ 下載 Node.js 的最新安裝包 (當前 2016.9.22 的最新版本是)。下載完安裝包 (例如 node-v6.6.0.pkg),雙擊進行安裝。參考提示進行,選擇默認選項就行瞭。

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

node --version

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

聊天服務器

你將用到一個聊天服務器。從這裡下載示例 iOS app 和 Web 服務器代碼。解壓縮 zip 包到桌面或者某個文件夾。在終端中,切換到該目錄,並進入 nodeapp 子目錄。

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

npm install websocket

輸入下列命令啟動聊天服務器:

node chat-server.js

你會看到類似如下輸出:

Tue Sep 13 2016 18:54:44 GMT-0500 (CDT) Server is listening on port 1337

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

輸入一個昵稱,發送一條測試消息。如果要在第二個客戶端進行測試,重新打開一個瀏覽器或標簽頁,用同一個 Url。用另一個昵稱登錄,發送一條消息;你會看到消息立即出現在另一個瀏覽器裡。

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

$ node chat-server.jsTue Sep 13 2016 18:54:44 GMT-0500 (CDT) Server is listening on port 1337Tue Sep 13 2016 18:55:19 GMT-0500 (CDT) Connection from origin null.Tue Sep 13 2016 18:55:19 GMT-0500 (CDT) Connection accepted.Tue Sep 13 2016 18:55:34 GMT-0500 (CDT) User is known as: Aaron with green color.Tue Sep 13 2016 18:55:37 GMT-0500 (CDT) Received Message from Aaron: HelloTue Sep 13 2016 18:58:49 GMT-0500 (CDT) Connection from origin null.Tue Sep 13 2016 18:58:49 GMT-0500 (CDT) Connection accepted.Tue Sep 13 2016 18:58:51 GMT-0500 (CDT) User is known as: James with red color.Tue Sep 13 2016 18:58:55 GMT-0500 (CDT) Received Message from James: This is pretty slick!Tue Sep 13 2016 18:59:03 GMT-0500 (CDT) Received Message from James: :]Tue Sep 13 2016 18:59:27 GMT-0500 (CDT) Peer undefined disconnected.

WebSockets

HTTP 第一次出現是 1991 年,它設計為一種請求/響應式的通訊機制。Web 瀏覽器用這種機制工作良好,用戶請求 web 頁,服務器返回內容。但某些時候,需要有新數據時不經過用戶請求就通知用戶——也就是,服務器推。

HTTP 協議無法很好地解決推模型。在 websocket 出現前,web 服務通過一系列瀏覽器刷新機制來實現推模型,但效率無法讓人滿意。

webSocket 實現瞭服務端推機制。新的 web 瀏覽器全都支持 WebSocket,這使得它的使用超級簡單。通過 WebSocket 能夠打開持久連接,大部分網絡都能輕松處理 WebSocket 連接。

WebSocket 通常應用在某些數據經常性或頻繁改變的場景。例如 Facebook 中的 web 通知、Slack 中的實時聊天、交易系統中的變化的股票價格。

在 iOS 中使用 WebSocket 比較麻煩,你必須進行大量的設置,而且內置的 API 根本幫不上忙。這時 Starscream 出現瞭——這個小巧、易於使用的庫讓你所有的煩惱不翼而飛。

Emoji Communicator

打開 EmojiTransmitter.xcodeproj。在模擬器中運行程序,程序很簡單,它需要用戶輸入一個昵稱,然後顯示一個界面,讓用戶選擇一個 emoji 發送,並顯示任何接收到的 emoji。

這個 App 還沒有完成網絡部分。你將使用 Starscream 來執行所有的 WebSocket 網絡請求。

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

首先,關閉打開的項目。開啟終端窗口,將目錄切換至項目文件夾。在這個項目中已經有一個配置瞭 Starscream pod 的 Podfile 文件瞭。你可以直接安裝 pod:

pod repo update; pod install

當 CocoaPods 結束安裝,在 Xcode 8 中打開 EmojiTransmitter.xcworkspace 文件。運行程序,檢查 App 是否能夠運行。
打開 ViewController.swift,在 import UIKit 後加入:

import Starscream

然後,在 ViewController 類的 username 屬性後增加一個屬性:

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

這是創建 WebSocket 連接的核心。註意 URL 的歌聲,協議是 ws 而不是 Http/https。protocols 參數指定為 chat,這取決於服務端的實現,這個協議可以被使用,也可能被忽略。在本 demo 中,忽略它即可。
接著在 viewDidLoad 方法後加入:

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

當 View Controller 被銷毀時,強制關閉 WebSocket 連接。

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

在 ViewController.swift,在 fileprivate 擴展後增加一個擴展:

// MARK: - WebSocketDelegate
extension ViewController : WebSocketDelegate {
  public func websocketDidConnect(_ socket: Starscream.WebSocket) {

  }

  public func websocketDidDisconnect(_ socket: Starscream.WebSocket, error: NSError?) {

  }

  public func websocketDidReceiveMessage(_ socket: Starscream.WebSocket, text: String) {

  }

  public func websocketDidReceiveData(_ socket: Starscream.WebSocket, data: Data) {

  }
}

這 4 個委托方法必須實現,否則代碼無法通過編譯。

然後,在 viewDidLoad 方法的 super.viewDidLoad() 後面添加:

socket.delegate = self
socket.connect()

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

現在,你已經能夠連接到 Node.js App 瞭,接下來是發送消息到服務器。

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

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

這會發送消息(本例中,就是 emoji)到 Node.js 服務器。

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

socket.write(string: username)

這會在連接建立後發送你在第一個界面中輸入的昵稱。這個服務器會將第一個接收到的消息當做用戶名稱。
在 websocketDidDisconnect(_:error:) 中加入:

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

無論什麼原因,隻要 socket 被斷開,這都會讓用戶返回到輸入昵稱界面。如果在你自己的 App 中,你應當在這裡進行更健全的錯誤處理。

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

// 1
guard let data = text.data(using: .utf16),
  let jsonData = try? JSONSerialization.jsonObject(with: data),
  let jsonDict = jsonData as? [String: Any],
  let messageType = jsonDict["type"] as? String else {
    return
}

// 2
if messageType == "message",
  let messageData = jsonDict["data"] as? [String: Any],
  let messageAuthor = messageData["author"] as? String,
  let messageText = messageData["text"] as? String {

  messageReceived(messageText, senderName: messageAuthor)
}

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

  1. 首先將字符串轉為 NSData,然後將 NSData 傳給 JSONSerialization 對象以將其轉為載體並返回一個有效的對象。最後還檢查瞭幾個重要的 key,並設置對應的值。如果對象無效,直接通過 guard 語句退出。
  2. 過濾消息的 messageType,然後將數據傳遞給 messageReceived(messageText:, senderName:) 方法。

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

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

運行 app,每當你發送一條消息,emoji 將會用你選擇的 emoji 和昵稱刷新。返回 web 控制臺,你的 emoji 消息也會顯示。

這就是 Starscream 的使用!

結束

在這裡下載最終完成的項目。

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

  • 參考 Starscream 在 GitHub 上的項目主頁 。
  • 參考 Mozilla 開發者網絡 上關於 WebSocket 的介紹和如何實現 WebSocket。
  • 如果你需要某些讓人昏昏欲睡的東西,請閱讀 RFC 6455 ,關於 WebSocket 協議規范。

如果你有任何問題或建議,請在下面留言。

到此這篇關於IOS之WebSocket框架Starscream案例詳解的文章就介紹到這瞭,更多相關IOS之WebSocket框架Starscream內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: