如何快速的開發一個完整的iOS直播app(搭建Socket即時通訊伺服器)

發表於2016-12-26

前言

在看這篇之前,如果您還不瞭解直播原理,請檢視這篇文章如何快速的開發一個完整的iOS直播app(原理篇)

在直播中,聊天和發禮物,需要用到及時通訊技術,市面上的App大多數採用的都是第三方SDK,融雲,環信等,但是本例子採用websocket搭建及時通訊伺服器。

即時通訊

即時通訊(Instant messaging,簡稱IM)是一個終端服務,允許兩人或多人使用網路即時的傳遞文字訊息、檔案、語音與視訊交流

即時通訊技術原理(瞭解Socket)

  • Socket介紹: 套接字或者插座,用於描述IP地址和埠號,是一種網路的通訊機制。
  • Socket作用: 網路通訊底層都是通過socket建立連線的,因為它包含IP和埠,只要有這兩個就能準確找到一臺主機上的某個應用。
  • IM通訊原理(T):
    • 客戶端A與客戶端B如何產生通訊?客戶端A不能直接和客戶端B,因為兩者相距太遠。
    • 這時就需要通過IM伺服器,讓兩者產生通訊.
    • 客戶端A通過socket與IM伺服器產生連線,客戶端B也通過socket與IM伺服器產生連線
    • A先把資訊傳送給IM應用伺服器,並且指定傳送給B,伺服器根據A資訊中描述的接收者將它轉發給B,同樣B到A也是這樣。
    • 通訊問題: 伺服器是不能主動連線客戶端的,只能客戶端主動連線伺服器
    • 那麼當伺服器要推資訊給客戶端B,但是客戶端B這時候沒有與伺服器產生連線,就推送不了.
    • 這樣就延遲,不即時了。

即時通訊技術實現

  • 即時通訊核心是即時`,那怎麼達到即時?
    • 目前實現即時通訊的有四種方式(短輪詢、長輪詢、SSE、Websocket)
    • 短輪詢: 每隔一小段時間就傳送一個請求到伺服器,伺服器返回最新資料,然後客戶端根據獲得的資料來更新介面,這樣就間接實現了即時通訊。優點是簡單,缺點是對伺服器壓力較大,浪費頻寬流量(通常情況下資料都是沒有發生改變的)。
    • 短輪詢: 主要是客戶端人員寫程式碼,伺服器人員比較簡單,適於小型應用
    • 長輪詢: 客戶端傳送一個請求到伺服器,伺服器檢視客戶端請求的資料(伺服器中資料)是否發生了變化(是否有最新資料),如果發生變化則立即響應返回,否則保持這個連線並定期檢查最新資料,直到發生了資料更新或連線超時。同時客戶端連線一旦斷開,則再次發出請求,這樣在相同時間內大大減少了客戶端請求伺服器的次數.
    • 長輪詢底層實現:在伺服器的程式中加入一個死迴圈,在迴圈中監測資料的變動。當發現新資料時,立即將其輸出給瀏覽器並斷開連線,瀏覽器在收到資料後,再次發起請求以進入下一個週期
    • 長輪詢弊端:伺服器長時間連線會消耗資源,返回資料順序無保證,難於管理維護
    • 長輪詢處理:不能一直持續下去,應該設定一個最長時限,可以通過心跳包的方式,設定多少秒沒有接到心跳包,就關閉當前連線。
    • 心跳包:就是在客戶端和伺服器間定時通知對方自己狀態的一個自己定義的命令字,按照一定的時間間隔傳送,類似於心跳,所以叫做心跳包
    • SSE(Server-sent Events伺服器推送事件):為了解決瀏覽器只能夠單向傳輸資料到服務端,HTML5提供了一種新的技術叫做伺服器推送事件SSE,SSE技術提供的是從伺服器單向推送資料給瀏覽器的功能,但是配合瀏覽器主動請求,實際上就實現了客戶端和伺服器的雙向通訊.
    • WebSocket:上面的這些解決方案中,都是利用瀏覽器單向請求伺服器或者伺服器單向推送資料到瀏覽器,而在HTML5中,為了加強web的功能,提供了websocket技術,它不僅是一種web通訊方式,也是一種應用層協議。它提供了瀏覽器和伺服器之間原生的全雙工跨域通訊,通過瀏覽器和伺服器之間建立websocket連線,在同一時刻能夠實現客戶端到伺服器和伺服器到客戶端的資料傳送.

WebSocket

  • 什麼是websocket?是 HTML5 一種新的協議。它實現了瀏覽器與伺服器全雙工通訊,能更好的節省伺服器資源和頻寬並達到實時通訊,它建立在 TCP 之上,同 HTTP 一樣通過 TCP 來傳輸資料
  • WebSocket 是一種雙向通訊協議,在建立連線後,WebSocket 伺服器和 客戶端 都能主動的向對方傳送或接收資料,就像 Socket 一樣。
  • WebSocket 需要類似 TCP 的客戶端和伺服器端通過握手連線,連線成功後才能相互通訊
  • websocket提供兩種資料傳輸:文字資料和二進位制資料
  • websocket協議頭:ws

WebSocket原理

  • Websocket流程(T): WB是先進行一次HTTP請求,這個請求頭不同於普通HTTP請求,然後伺服器開始辨認請求頭,如果是WB的請求頭,則開始進行普通的TCP連線,即三次握手。如果不是WB的HTTP請求頭,那就是按普通的HTTP請求處理
  • Websocket協議解析:
    • 請求頭
    • 響應頭
    • Sec-WebSocket-Key:其值採用base64編碼的隨機16位元組長的字元序列
    • Sec-WebSocket-Accept如何生成

Socket.IO簡介

  • WebSocket的功能是很強大的,使用起來也靈活,可以適用於不同的場景。不過WebSocket技術也比較複雜,需要加密解密,包裝協議,自己實現3次握手,還需要對資料流進行加密解密處理,伺服器端和瀏覽器端的實現都不同於一般的Web應用,因此自己實現很麻煩,可以使用Socket.IO框架。
  • Socket.IO:是一個完全由JavaScript實現、基於Node.js、支援WebSocket的協議用於實時通訊、跨平臺的開源框架。
  • Socket.IO:它包括了客戶端(iOS,Android)和伺服器端(Node.js)的程式碼,可以很好的實現iOS即使通訊技術。
  • Socket.IO框架地址

Socket.IO教程

Socket.IO建立連線 伺服器程式碼

  • 1.如何匯入Socket.IO?
    • 和匯入express框架一樣,使用package
    • 給package檔案新增依賴

  • 2.如何建立socket
    • socket本質還是http協議,所以需要繫結http伺服器,才能啟動socket服務.
    • 而且需要通過web伺服器監聽埠,socket不能監聽埠,有人訪問埠才能建立連線,所以先建立web伺服器

  • 3.如何建立socket連線(伺服器不需要主動建立連線,建立連線是客戶端的事情,伺服器只需要監聽連線)
    • 客戶端主動連線會傳送connection事件,只需要監聽connection事件有沒有傳送,就知道客戶端有沒有主動連線伺服器
    • Socket.IO本質是通過傳送和接受事件觸發伺服器和客戶端之間的通訊,任何能被編輯成JSON或二進位制的物件都可以傳遞。
    • 監聽事件,用socket.on,這個方法會有兩個引數,第一個引數是事件名稱,第二個引數是監聽事件的回撥函式,監聽到就會執行這個回撥函式
    • 監聽connection,回撥函式會傳入一個連線好的socket,這個socket就是客戶端的socket
    • socket連線原理,就是客戶端和服務端通過socket連線,伺服器有socket,客戶端也有

    • 書寫客戶端程式碼,驗證是否能建立連線

Socket.IO建立連線 客戶端程式碼

  • 1.下載Socket.IO-Client-Swift
    • Socket.IO只有swift,如果需要用OC程式碼,需要swift和OC混編
    • 還有如果程式碼是OC,並且使用cocoapods,就不要使用cocoapods匯入swift程式碼,會有問題.
  • 2.下載完了,直接把Source資料夾拖入到自己工程中.
    • 會報錯,說當前swift版本過時,需要更新。點選Xcode頂部Edit => Convert => TO Current Swift Syntas 就好了。
  • 3.OC和Swift混編,Swift程式碼怎麼在OC中使用,直接匯入”工程檔名-Swift.h”就可以使用,這個檔案Xcode會自動幫我們生成,無序手動自己生成.

  • 4.注意工程檔名不能帶有-這個符號,而且有時候會延遲,並不是馬上匯入”工程檔名-Swift.h”就好.
  • 5.建立socket物件,然後連線用connect方法,socket物件需要強引用
    • 注意協議:ws開頭
    • 建立socket物件,需要傳入字典,字典配置如下。
  • 6.因為需要進行3次握手,不可能馬上建議連線,需要監聽是否連線成功的回撥,使用on方法
  • 7.ON方法兩個引數(第一個引數,監聽的事件名稱,第二個引數:監聽事件回撥函式,會自動呼叫)
    • 回撥函式也有兩個引數(第一個引數:伺服器傳遞的資料 第二個引數:確認請求資料)
    • 在TCP/IP協議中,如果接收方成功的接收到資料,那麼會回覆一個ACK資料。

SocketIO傳送事件,通過事件傳遞資料

SocketIO 客戶端傳送事件程式碼

  • 注意:只有連線成功之後,才能傳送事件
  • 向伺服器傳送事件(emit:第一引數事件的名稱,第二個引數傳輸的資料,是一個陣列)

SocketIO 伺服器監聽事件程式碼

  • 監聽客戶端事件,需要巢狀在連線好的connect回撥函式中
  • 必須使用回撥函式的socket引數,如function(s)中的s,監聽事件,因此這是客戶端的socket,肯定監聽客戶端發來的事件
  • 伺服器監聽連線的回撥函式的引數可以新增多個,具體看客戶端傳遞資料陣列有幾個,每個引數都是與客戶段一一對應,第一個引數對應客戶端陣列第0個資料

SocketIO 伺服器傳送事件程式碼

  • 這裡的socket一定要用伺服器端的socket
  • 給當前客戶端傳送資料,其他客戶端收不到.

  • 發給所有客戶端,不包含當前客戶端

  • 發給所有客戶端,包含當前客戶端

SocketIO 客戶端監聽事件程式碼

SocketIO分組

  • 開發中什麼場景需要使用SocketIO分組?(T)
  • 一個客戶端和伺服器只會保持一個socket連線,比如直播App中會開很多主播房間,每個房間都有自己的聊天室,那怎麼把資訊推送到對應的房間,比如A使用者要給A主播間傳送資訊,怎麼推送過去,通過伺服器只能給當前客戶端推送,那一推,當前客戶端所有直播間都有A使用者的資訊。
  • 怎麼解決多個直播聊天室問題?
  • 給每個主播的房間都分組,伺服器就可以給指定組推送資料,就不會影響到其他直播間
  • SocketIO如何分組?
    • 伺服器程式碼: socket.join(),()裡面放分組名稱,與之對應的 socket.leave()
    • 注意這裡的socket是客戶端的socket,也就是連線成功,傳遞過來的socket
  • socket分組的原理,只要客戶端socket呼叫join,伺服器就會把客戶端socket和分組的名稱繫結起來,到時候就可以根據分組的名稱找到對應客戶端的socket,就能給指定的客戶端推送資訊.
  • 注意:一個客戶端socket只能新增到一組,離開的時候,要記得移除.
  • 客戶端可以這樣測試,搞兩臺電腦/兩臺手機在同一個區域網內,執行就有兩個客戶端,分別加入不同組.
  • 伺服器只給一個客戶端socket傳送資訊,另外一個客戶端收不到
  • 伺服器程式碼

相關文章