WebSocket 握手是客戶端和伺服器之間建立 WebSocket 連線的第一步。它本質上是一個 HTTP 請求和響應,用於升級協議從 HTTP 到 WebSocket。以下是握手的具體步驟:
1. 客戶端傳送 WebSocket 握手請求:
客戶端向伺服器傳送一個 HTTP 請求,其中包含一些特殊的頭部資訊,表明它想要升級到 WebSocket 協議。這個請求通常是一個 GET 請求,指向 ws:// 或 wss:// (加密連線) 開頭的 URI。
關鍵的頭部資訊包括:
- Connection: Upgrade: 表示客戶端希望升級到不同的協議。
- Upgrade: websocket: 指定要升級到的協議是 WebSocket。
- Sec-WebSocket-Key: 一個隨機生成的 Base64 編碼的字串,用於防止代理伺服器快取和重用握手。伺服器必須使用這個 key 進行特定的計算並返回結果。
- Sec-WebSocket-Version: 指定客戶端支援的 WebSocket 協議版本,通常是 13。
- Origin (可選): 指示請求的來源,用於安全策略。
- Sec-WebSocket-Protocol (可選): 客戶端支援的子協議列表,伺服器可以選擇其中一個。
- Sec-WebSocket-Extensions (可選): 客戶端希望使用的擴充套件。
示例請求:
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Version: 13
2. 伺服器響應 WebSocket 握手請求:
如果伺服器同意建立 WebSocket 連線,它會返回一個 HTTP 101 Switching Protocols 響應。這個響應也包含一些特殊的頭部資訊,確認升級到 WebSocket 協議。
關鍵的頭部資訊包括:
- Upgrade: websocket: 確認升級到 WebSocket 協議。
- Connection: Upgrade: 確認連線升級。
- Sec-WebSocket-Accept: 伺服器根據客戶端提供的 Sec-WebSocket-Key 計算出的值。這是握手過程中至關重要的一步,用於證明伺服器確實收到了客戶端的請求並同意建立 WebSocket 連線。計算方法是將 Sec-WebSocket-Key 與一個固定的 GUID ("258EAFA5-E914-47DA-95CA-C5AB0DC85B11") 連線起來,然後計算 SHA-1 雜湊值,最後將雜湊值進行 Base64 編碼。
示例響應:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
3. 連線建立:
一旦客戶端收到伺服器的 101 響應,WebSocket 連線就建立完成了。客戶端和伺服器就可以開始雙向通訊,傳送和接收 WebSocket 資料幀。
如果握手失敗:
如果伺服器拒絕建立 WebSocket 連線,它會返回一個普通的 HTTP 錯誤響應,例如 400 Bad Request 或 404 Not Found。客戶端可以透過檢查響應的狀態碼來判斷握手是否成功。
前端開發中的 WebSocket 握手:
在前端開發中,通常使用 JavaScript 的 WebSocket API 來建立 WebSocket 連線。開發者無需手動構建 HTTP 請求和解析響應,WebSocket API 會自動處理握手過程。
const socket = new WebSocket('ws://example.com/chat');
socket.onopen = function(event) {
console.log('WebSocket connection opened');