1. 程式人生 > >Java WebSocket程式設計(二):WebSocket實現主動推送互動

Java WebSocket程式設計(二):WebSocket實現主動推送互動

WebSocket協議

WebSocket協議通訊機制

WebSocket協議是獨立的、基於TCP的協議。其本質是先通過HTTP/HTTPS協議進行握手後建立一個用於交換資料的TCP連線,此後伺服器端與客戶器端通過此TCP連線進行實時通訊。
這裡寫圖片描述


WebSocket開啟握手

每個socket連線都始於一個HTTP請求,該請求包含一個特殊的首標Upgrade。Upgrade首標表示客戶端會將連線升級到不同的協議。在這種情況下,這個不同的協議就是WebSocket。

傳送握手請求

客戶端通過HTTP協議傳輸WebSocket支援的版本號、HTTP協議的版本號、原始地址和主機地址等欄位給伺服器端。客戶端傳送的HTTP請求程式碼如下:

GET /chat HTTP 1.1
Host: server.example.com
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13

這個升級的請求頭增加了以下欄位:

  • Sec-WebSocket-Protocol:客戶端可以接收的子協議的型別,即在WebSocket協議之上的應用層協議型別。
  • Connection:告知伺服器端當前請求連線是升級的HTTP請求。
  • Origin:防止客戶端使用指令碼進行未授權的跨源攻擊。伺服器端根據這個欄位判斷是否接受客戶端的Socket連線。可以返回一個HTTP錯誤狀態碼來拒絕連線。
  • Sec-WebSocket-Key:為了表示伺服器端同意和客戶端進行Socket連線,伺服器端需要使用該欄位進行校驗,然後返回一個校驗過的字串給客戶端,客戶端驗證通過後才能正式建立Socket連線。
  • Sec-WebSocket-Version:表示版本相容性。

返回握手應答

WebSocket伺服器端收到客戶端傳送的握手請求後,如果資料包資料和格式正確,客戶端和伺服器端的協議版本號匹配等,就接收本次握手鍊接,並給出響應的資料回覆。伺服器端返回的響應程式碼如下:

HTTP/1.0 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: xxxxxxxxxxxxxxxxxxxxxxxx
Sec-WebSocket-Protocol: chat

響應程式碼中包含以下欄位:

  • Sec-WebSocket-Accept:伺服器端將加密處理後的握手Key通過這個欄位返回給客戶端,表示同意握手建立連線。
  • Sec-WebSocket-Protocol:伺服器選擇的一個應用層協議。

客戶端收到伺服器端回覆的資料包後,如果資料包內容、格式都正確,就表示本次連線成功,升級為WebSocket協議,這也稱作WebSocket初始握手(Opening Handshak)。


資料幀傳輸格式

WebSocket連線開啟時,客戶端和伺服器端可以互相傳送資料,資料使用一系列幀來傳輸。基本的資料幀由一個opcode、一個payload長度和傳送的應用資料等組成。

  0                   1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-------+-+-------------+-------------------------------+
 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
 | |1|2|3|       |K|             |                               |
 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
 |     Extended payload length continued, if payload len == 127  |
 + - - - - - - - - - - - - - - - +-------------------------------+
 |                               |Masking-key, if MASK set to 1  |
 +-------------------------------+-------------------------------+
 | Masking-key (continued)       |          Payload Data         |
 +-------------------------------- - - - - - - - - - - - - - - - +
 :                     Payload Data continued ...                :
 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
 |                     Payload Data continued ...                |
 +---------------------------------------------------------------+
  • FIN:1bit,表示是訊息的最後一幀。
  • RSV1,RSV2,RSV3:每個1bit,必須是零,除非擴充套件定義為非零,如果接收到的是非零值但是擴充套件沒有定義,則需要關閉連線。
  • Opcode:4bit,解釋payload資料,規定有以下不同的狀態,如果未知則接收方馬上關閉連線。狀態如下:0x0(附加資料幀)、0x1(文字資料幀)、0x2(二進位制資料幀)、0x3-7(保留為之後非控制幀使用)、0xB-F(保留位後面的控制幀使用)、0x8(關閉連線幀)、0x9(ping)、0xA(pong)。
  • Mask:1bit,掩碼,定義payload資料是否進行了掩碼處理。
  • Masking-Key: 0到4子節,掩碼解密金鑰,用於解碼Payload Data。客戶端發出的資料幀需要進行亞麻處理,所以此位是1。
  • Payload length:7bit、7+16bit或7+64bit。payload Data的長度。
  • Payload data:任意長度資料。包含有擴充套件定義資料和應用資料。

WebSocket關閉握手

正常關閉握手的步驟:

  1. 當一端接收到一個關閉幀,且先前沒有傳送關閉幀,則這一端必須傳送一個關閉幀作為響應。
  2. 當接收到這個響應幀時,接收這一端關閉連線,同時傳送表明關閉連線的控制幀,不再發送資料。
  3. 另一端接收到表示應該關閉連線的控制幀後,丟棄後面接收的所有資料,關閉連線。

但是TCP關閉握手並不總是端到端可靠的,特別是出現攔截代理和其他的中間設施。當WebSocket關閉時,終止連線的端點可以傳送一個數字程式碼,以及一個表示選擇關閉套接字原因的字串。程式碼1000~1015規定用於WebSocket連線層。


WebSocket協議通訊實現的相關技術

WebSocket建構函式

WebSocket建構函式語法格式如下:

var ws = new WebSocket("ws://127.0.0.1/WebSocket/websocket")

URL地址的字串需要以“ws”或“wss”(加密通訊時使用)作為開頭。


WebSocket事件

客戶端的應用程式通過監聽WebSocket物件上的事件,來及時處理資料和改變連線的狀態。WebSocket物件可以觸發4種事件,包括

  • open事件:WebSocket連線建立。
  • message事件:客戶端接收到伺服器端的資料。
  • error事件:通訊過程中發生錯誤。
  • close事件:連線關閉。

WebSocket方法

  • send()方法:傳送資料到伺服器端。
  • close()方法:關閉WebSocket連線。可選引數:code(數字型的狀態程式碼)、reason(文字字串)。