前言:
前段時間,在公司的項目中用到了WebSocket
,當時沒有時間好好整理。
最近,趁着有時間,就好好梳理了一下WebSocket
的相關知識。git
本篇將介紹如下內容:
一、什麼是WebSocket
?
二、WebSocket
使用場景
三、WebSocket
底層原理(協議)
四、iOS
中WebSocket
的相關框架github
WebSocket = 「HTTP第1次握手」 + TCP
的「全雙工「通訊 的網絡協議。web
主要過程:objective-c
HTTP
第一次握手保證鏈接成功。TCP
實現瀏覽器與服務器全雙工(full-duplex
)通訊。(經過不斷髮ping
包、pang
包保持心跳)最終,使得 「服務端」 擁有 「主動」 發消息給 「客戶端」 的能力。swift
這裏有幾個重點:瀏覽器
WebSocket
是基於TCP
的上部應用層網絡協議。HTTP
的第一次握手成功 + 以後的TCP
雙向通訊。典型例子:微信、QQ等 固然,用戶量若是很是大的話,僅僅依靠WebSocket
確定是不夠的,各大廠應該也有本身的一些優化的方案與措施。但對於用戶量不是很大的即時通信需求,使用WebSocket
是一種不錯的方案。服務器
典型例子:王者榮耀等(應該都玩過)微信
多人同時編輯同一份文檔時,能夠實時看到對方的操做。 這時,就用上了WebSocket
。websocket
對音頻/視頻須要較高的實時性。
對於股票/基金的交易來講,每一秒的價格可能都會發生變化。
例如,咱們的App須要實時的獲取智能設備的數據與狀態。 這時,就須要用到WebSocket
。
...... 等等等等
只要是一些對 「實時性」 要求比較高的需求,可能就會用到WebSocket
。
WebSocket
是一個網絡上的應用層協議,它依賴於HTTP
協議的第一次握手,握手成功後,數據就經過TCP/IP
協議傳輸了。
WebSocket
分爲握手階段和數據傳輸階段,即進行了HTTP
一次握手 + 雙工的TCP
鏈接。
首先,客戶端發送消息:
GET /chat HTTP/1.1
Host: server.qishare.org
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://qishare.org
Sec-WebSocket-Version: 13
複製代碼
而後,服務端返回消息:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
複製代碼
這裏值得注意的是Sec-WebSocket-Accept
的計算方法: base64(hsa1(sec-websocket-key + 258EAFA5-E914-47DA-95CA-C5AB0DC85B11))
Sec-WebSocket-Accept
計算錯誤,瀏覽器會提示:Sec-WebSocket-Accept dismatch
;Websocket
就會回調onopen
事件WebSocket
是以 frame
的形式傳輸數據的。 好比會將一條消息分爲幾個frame
,按照前後順序傳輸出去。
這樣作會有幾個好處:
HTTP
的chunk
同樣,能夠邊生成數據邊傳遞消息,即提升傳輸效率。WebSocket
傳輸過程使用的報文,以下所示:
具體的參數說明以下:
FIN(1 bit): 表示信息的最後一幀,flag,也就是標記符。 PS:固然第一個消息片段也多是最後的一個消息片段;
RSV一、RSV二、RSV3(均爲1 bit): 默認均爲0。若是有約定自定義協議則不爲0,通常均爲0。(協議擴展用)
Opcode(4 bit): 定義有效負載數據,若是收到了一個未知的操做碼,鏈接也必須斷掉,如下是定義的操做碼:
操做碼 | 含義 |
---|---|
%x0 | 連續消息片段 |
%x1 | 文本消息片段 |
%x2 | 二進制消息片段 |
%x3-7 | (預留位)爲未來的非控制消息片段保留的操做碼。 |
%x8 | 鏈接關閉 |
%x9 | 心跳檢查ping |
%xA | 心跳檢查pong |
%xB-F | (預留位)爲未來的控制消息片段的保留操做碼。 |
Mask(1 bit): 是否傳輸數據添加掩碼。 若爲1,掩碼必須放在masking-key區域。(後面會提到..) 注:客戶端給服務端發消息Mask
值均爲1
。
Payload length: Payload字段用來存儲傳輸數據的長度。
自己Payload報文字段的大小可能有三種狀況:7 bit
、7+16 bit
、7+64 bit
。
第一種:7 bit
,表示從0000000
~ 1111101
(即0
~125
),表示當前數據的length大小(較小數據,最大長度爲125)。
第二種:(7+16) bit
:前7位爲1111110(即126)
,126
表明後面會跟着2個字節無符號數,用來存儲數據length大小(長度最小126,最大爲65 535)。
第三種:(7+64) bit
:前7位爲1111111(即127)
,127
表明後面會跟着8個字節無符號數,用來存儲數據length大小(長度最小爲65536,最大爲2^16-1)。
Payload報文長度 | 所傳輸的數據大小區間 |
---|---|
7 bit | [ 0, 125] |
7 +16 bit | [ 126 , 65535] |
7 + 64 bit | [ 65536, 2^16 -1] |
說明:
傳輸數據的長度,以字節的形式表示:7位、7+16位、或者7+64位。
1)若是這個值以字節表示是0-125這個範圍,那這個值就表示傳輸數據的長度;
2)若是這個值是126,則隨後的2個字節表示的是一個16進制無符號數,用來表示傳輸數據的長度;
3)若是這個值是127,則隨後的是8個字節表示的一個64位無符號數,這個數用來表示傳輸數據的長度。
0 bit
:說明mask值不爲1
,無掩碼。4 bit
:說明mask值爲1
,添加掩碼。PS:客戶端發送給服務端數據時,
mask
均爲1。 同時,Masking-key
會存儲一個32位的掩碼。
Payload data(x+y byte): 負載數據爲擴展數據及應用數據長度之和。
Extension data(x byte): 若是客戶端與服務端之間沒有特殊約定,那麼擴展數據的長度始終爲0,任何的擴展都必須指定擴展數據的長度,或者長度的計算方式,以及在握手時如何肯定正確的握手方式。若是存在擴展數據,則擴展數據就會包括在負載數據的長度以內。
Application data(y byte): 任意的應用數據,放在擴展數據以後。 應用數據的長度 = 負載數據的長度 - 擴展數據的長度
即:Application data = Payload data - Extension data
Starscream(swift): Websockets in swift for iOS and OSX.(star 5k+
)
SocketRocket(objective-c): A conforming Objective-C WebSocket client library.(star:8k+
)
SwiftWebSocket(swift): Fast Websockets in Swift for iOS and OSX.(star:1k+
)
CocoaAsyncSocket: Asynchronous socket networking library for Mac and iOS.(star:11k+
)
socket.io-client-swift: Socket.IO-client for iOS/OS X.(star:4k+
)
下一篇,咱們將用Starscream寫一個簡單的客戶端WebSocket Demo。
相關參考連接:
《微信,QQ這類IM app怎麼作——談談Websocket》(冰霜大佬)
《WebSocket的實現原理》 `
小編微信:可加並拉入《QiShare技術交流羣》。
關注咱們的途徑有:
QiShare(簡書)
QiShare(掘金)
QiShare(知乎)
QiShare(GitHub)
QiShare(CocoaChina)
QiShare(StackOverflow)
QiShare(微信公衆號)
推薦文章:
用 Swift 進行貝塞爾曲線繪製
Swift 5.1 (11) - 方法
Swift 5.1 (10) - 屬性
iOS App後臺保活
奇舞週刊