WebSocket原理及技術簡介

jayqiu發表於2018-08-30

WebSocket原理及技術簡介

1. websocket

Websocket是html5提出的一個協議規範,參考rfc6455。

websocket約定了一個通訊的規範,通過一個握手的機制,客戶端(瀏覽器)和伺服器(webserver)之間能建立一個類似tcp的連線,從而方便c-s之間的通訊。在websocket出現之前,web互動一般是基於http協議的短連線或者長連線。

WebSocket是為解決客戶端與服務端實時通訊而產生的技術。websocket協議本質上是一個基於tcp的協議,是先通過HTTP/HTTPS協議發起一條特殊的http請求進行握手後建立一個用於交換資料的TCP連線,此後服務端與客戶端通過此TCP連線進行實時通訊。

2.websocket的優點

以前web server實現推送技術或者即時通訊,用的都是輪詢(polling),在特點的時間間隔(比如1秒鐘)由瀏覽器自動發出請求,將伺服器的訊息主動的拉回來,在這種情況下,我們需要不斷的向伺服器傳送請求,然而HTTP request 的header是非常長的,裡面包含的資料可能只是一個很小的值,這樣會佔用很多的頻寬和伺服器資源。

而最比較新的技術去做輪詢的效果是Comet – 用了AJAX。但這種技術雖然可達到全雙工通訊,但依然需要發出請求(reuqest)。

WebSocket API最偉大之處在於伺服器和客戶端可以在給定的時間範圍內的任意時刻,相互推送資訊。 瀏覽器和伺服器只需要要做一個握手的動作,在建立連線之後,伺服器可以主動傳送資料給客戶端,客戶端也可以隨時向伺服器傳送資料。 此外,伺服器與客戶端之間交換的標頭資訊很小。

WebSocket並不限於以Ajax(或XHR)方式通訊,因為Ajax技術需要客戶端發起請求,而WebSocket伺服器和客戶端可以彼此相互推送資訊;

WebSocket原理及技術簡介

因此從伺服器角度來說,websocket有以下好處:

節省每次請求的header
http的header一般有幾十位元組
Server Push
伺服器可以主動傳送資料給客戶端

3.websocket邏輯

與http協議不同的請求/響應模式不同,Websocket在建立連線之前有一個Handshake(Opening Handshake)過程,在關閉連線前也有一個Handshake(Closing Handshake)過程,建立連線之後,雙方即可雙向通訊。 在websocket協議發展過程中前前後後就出現了多個版本的握手協議,這裡分情況說明一下:

  • 基於flash的握手協議

使用場景是IE的多數版本,因為IE的多數版本不都不支援WebSocket協議,以及FF、CHROME等瀏覽器的低版本,還沒有原生的支援WebSocket。此處,server唯一要做的,就是準備一個WebSocket-Location域給client,沒有加密,可靠性很差。

客戶端請求:

GET /ls HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: www.qixing318.com
Origin: http://www.qixing318.com
複製程式碼

伺服器返回:

HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://www.qixing318.com
WebSocket-Location: ws://www.qixing318.com/ls
複製程式碼

4.Data Framing

Websocket協議通過序列化的資料幀傳輸資料。資料封包協議中定義了opcode、payload length、Payload data等欄位。其中要求:

  • 1.客戶端向伺服器傳輸的資料幀必須進行掩碼處理:伺服器若接收到未經過掩碼處理的資料幀,則必須主動關閉連線。
  • 2.伺服器向客戶端傳輸的資料幀一定不能進行掩碼處理。客戶端若接收到經過掩碼處理的資料幀,則必須主動關閉連線。 針對上情況,發現錯誤的一方可向對方傳送close幀(狀態碼是1002,表示協議錯誤),以關閉連線。 具體資料幀格式如下圖所示:

WebSocket原理及技術簡介

FIN
  • 標識是否為此訊息的最後一個資料包,佔 1 bit
RSV1, RSV2, RSV3: 用於擴充套件協議,一般為0,各佔1bit
  • 其中最重要的欄位為opcode(4bit)和MASK(1bit):

  • MASK值,從客戶端進行傳送的幀必須置此位為1,從伺服器傳送的幀必須置為0。如果任何一方收到的幀不符合此要求,則傳送關閉幀(Close frame)關閉連線。

  • opcode的值: 0x1代表此幀為文字資料幀, 0x2代表此幀為二進位制資料幀, 0x8為控制幀中的連線關閉幀(close frame), 0x9為控制幀中的Ping幀, 0xA(十進位制的10)為控制幀中的Pong幀。

  • Ping/Pong幀: Ping幀和Pong幀用於連線的保活(keepalive)或者診斷對端是否線上。這兩種幀的傳送和接收不對WEB應用公開介面,由實現WebSocket協議的底層應用(例如瀏覽器)來實現它。

MASK:佔1bits
  • 用於標識PayloadData是否經過掩碼處理。如果是1,Masking-key域的資料即是掩碼金鑰,用於解碼PayloadData。客戶端發出的資料幀需要進行掩碼處理,所以此位是1
Payload length
  • Payload data的長度,佔7bits,7+16bits,7+64bits:

    1.如果其值在0-125,則是payload的真實長度。 2.如果值是126,則後面2個位元組形成的16bits無符號整型數的值是payload的真實長度。注意,網路位元組序,需要轉換。 3.如果值是127,則後面8個位元組形成的64bits無符號整型數的值是payload的真實長度。注意,網路位元組序,需要轉換。 這裡的長度表示遵循一個原則,用最少的位元組表示長度(儘量減少不必要的傳輸)。舉例說,payload真實長度是124,在0-125之間,必須用前7位表示;不 允許長度1是126或127,然後長度2是124,這樣違反原則。

Payload data

應用層資料

server解析client端的資料

接收到客戶端資料後的解析規則如下:

1byte
  • 1bit: frame-fin,x0表示該message後續還有frame;x1表示是message的最後一個frame
  • 3bit: 分別是frame-rsv1、frame-rsv2和frame-rsv3,通常都是x0
  • 4bit: frame-opcode,x0表示是延續frame;x1表示文字frame;x2表示二進位制frame;x3-7保留給非控制frame;x8表示關 閉連線;x9表示ping;xA表示pong;xB-F保留給控制frame
2byte
  • 1bit: Mask,1表示該frame包含掩碼;0表示無掩碼
  • 7bit、7bit+2byte、7bit+8byte: 7bit取整數值,若在0-125之間,則是負載資料長度;若是126表示,後兩個byte取無符號16位整數值,是負載長度;127表示後8個 byte,取64位無符號整數值,是負載長度
  • 3-6byte: 這裡假定負載長度在0-125之間,並且Mask為1,則這4個byte是掩碼
  • 7-end byte: 長度是上面取出的負載長度,包括擴充套件資料和應用資料兩部分,通常沒有擴充套件資料;若Mask為1,則此資料需要解碼,解碼規則為- 1-4byte掩碼迴圈和資料byte做異或操作。

5.連線關閉

任何一端傳送關閉幀給對方,即可關閉連線。關閉連線時通常都帶有關閉連線的狀態碼(status code)。常見狀態碼的含義如下:

  • 1000 連線正常關閉
  • 1001 端點離線,例如伺服器down,或者瀏覽器已經離開此頁面
  • 1002 端點因為協議錯誤而中斷連線
  • 1003 端點因為受到不能接受的資料型別而中斷連線
  • 1004 保留
  • 1005 保留, 用於提示應用未收到連線關閉的狀態碼
  • 1006 端點異常關閉
  • 1007 端點收到的資料幀型別不一致而導致連線關閉
  • 1008 資料違例而關閉連線
  • 1009 收到的訊息資料太大而關閉連線
  • 1010 客戶端因為伺服器未協商擴充套件而關閉
  • 1011 伺服器因為遭遇異常而關閉連線
  • 1015 TLS握手失敗關閉連線

推薦1

推薦2

Star 我的GitHub

# Back

相關文章