以前總結了關於Websocket協議的握手鍊接方式等其餘細節,如今對socket鏈接創建後的數據幀傳輸和關閉細節總結。web
數據傳輸使用的是一系列數據幀,出於安全考慮和避免網絡截獲,客戶端發送的數據幀必須進行掩碼處理後才能發送到服務器,不管是否是在TLS安全協議上都要進行掩碼處理。服務器若是沒有收到掩碼處理的數據幀時應該關閉鏈接,發送一個1002的狀態碼。服務器不能將發送到客戶端的數據進行掩碼處理,若是客戶端收到掩碼處理的數據幀必須關閉鏈接。算法
基本的數據幀爲一個opcode、一個payload長度和發送的應用數據,根據ABNF的定義,詳細信息以下圖緩存
這裏使用的是數據存儲的位(bit),當進行加密的時候,最終要的一位就是最左邊的第一個。安全
Masking-key域的數據便是掩碼密鑰,用於解碼PayloadData。客戶端發出的數據幀須要進行掩碼處理,因此此位是1。
分片目的是發送長度未知的消息。若是不分片發送,即一幀,就須要緩存整個消息,計算其長度,構建frame併發送;使用分片的話,可以使用一個大小合適的buffer,用消息內容填充buffer,填滿即發送出去。服務器
分片規則:websocket
1.一個未分片的消息只有一幀(FIN爲1,opcode非0)網絡
2.一個分片的消息由起始幀(FIN爲0,opcode非0),若干(0個或多個)幀(FIN爲0,opcode爲0),結束幀(FIN爲1,opcode爲0)。併發
3.控制幀能夠出如今分片消息中間,但控制幀自己不容許分片。socket
4.分片消息必須按次序逐幀發送。加密
5.若是未協商擴展的狀況下,兩個分片消息的幀之間不容許交錯。
6.可以處理存在於分片消息幀之間的控制幀
7.發送端爲非控制消息構建長度任意的分片
8.client和server兼容接收分片消息與非分片消息
9.控制幀不容許分片,中間媒介不容許改變分片結構(即爲控制幀分片)
10.若是使用保留位,中間媒介不知道其值表示的含義,那麼中間媒介不容許改變消息的分片結構
11.若是協商擴展,中間媒介不知道,那麼中間媒介不容許改變消息的分片結構,一樣地,若是中間媒介不瞭解一個鏈接的握手信息,也不容許改變該鏈接的消息的分片結構
12.因爲上述規則,一個消息的全部分片是同一數據類型(由第一個分片的opcode定義)的數據。由於控制幀不容許分片,因此一個消息的全部分片的數據類型是文本、二進制、opcode保留類型中的一種。
須要注意的是,若是控制幀不容許夾雜在一個消息的分片之間,延遲會較大,好比說當前正在傳輸一個較大的消息,此時的ping必須等待消息傳輸完成,才能發送出去,會致使較大的延遲。爲了不相似問題,須要容許控制幀夾雜在消息分片之間。
數據幀示例:
未掩碼處理的文本單數據幀: 0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains "Hello")
掩碼處理的文本單數據幀: 0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58
分片未掩碼處理的文本消息: 0x01 0x03 0x48 0x65 0x6c (contains "Hel")
0x80 0x02 0x6c 0x6f (contains "lo")
未掩碼處理的Ping請求和掩碼處理的響應:
0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains a body of "Hello", but the contents of the body are arbitrary)
0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (contains a body of "Hello", matching the body of the ping)
64K的二進制數據:0x82 0x7F 0x0000000000010000 [65536 bytes of binary data]
爲了接收WebSocket數據,端點監聽底層網絡鏈接。傳入數據必須解析爲WebSocket幀。當接收到一個數據幀時,端點必須注意由操做碼(幀-opcode)定義的數據的/type/。這個幀的「應用數據」被定義爲消息的/data/。若是幀由一個未分片的消息組成,這是說已經接收到一個WebSocket消息,其類型爲/type/且數據爲/data/。若是幀是一個分片消息的一部分,隨後數據幀的「應用數據」鏈接在一塊兒造成/data/。當接收到由FIN位(幀-fin)指示的最後的片斷時,這是說已經接收到一個WebSocket消息,其數據爲/data/(由連續片斷的「應用數據」組成)且類型爲/type/(分配消息的第一個幀指出)。隨後的數據幀必須被解釋爲屬於一個新的WebSocket消息。
擴展能夠改變數據如何讀的語義,尤爲包括什麼組成一個消息的邊界。擴展,除了在負載中的「應用數據」以前添加「擴展數據」外,也能夠修改「應用數據」(例如壓縮它)。服務器必須爲從客戶端接收到的數據幀移除掩碼。
通訊的兩端中任意一端關閉均可以關閉socket鏈接,關閉時應該清楚全部的TCP鏈接資源和TLS回話的資源,同時要丟棄全部的可能接收的字節數據。首先關閉的一方通常都應該是服務器端,而後處於TIME_WAIT狀態。
爲了使用一個狀態碼關閉websocket,一端必須發送一個關閉的控制幀,當兩端都發送了關閉數據幀時,雙方都要關閉全部的鏈接資源。控制幀爲一個「狀態碼」和一個「緣由說明」,當關閉以後,雙方處於CLOSED狀態。