一、 簡介1.1 什么是WebSocketWebSocket是一種協(xié)議,用于在Web應(yīng)用程序和服務(wù)器之間建立實(shí)時(shí)、雙向的通信連接。它通過一個(gè)單一的TCP連接提供了持久化連接,這使得Web應(yīng)用程序可以更加實(shí)時(shí)地傳遞數(shù)據(jù)。WebSocket協(xié)議最初由W3C開發(fā),并于2011年成為標(biāo)準(zhǔn)。
1.2 WebSocket的優(yōu)勢和劣勢WebSocket的優(yōu)勢包括:
實(shí)時(shí)性: 由于WebSocket的持久化連接,它可以實(shí)現(xiàn)實(shí)時(shí)的數(shù)據(jù)傳輸,避免了Web應(yīng)用程序需要不斷地發(fā)送請求以獲取最新數(shù)據(jù)的情況。
雙向通信: WebSocket協(xié)議支持雙向通信,這意味著服務(wù)器可以主動向客戶端發(fā)送數(shù)據(jù),而不需要客戶端發(fā)送請求。
減少網(wǎng)絡(luò)負(fù)載: 由于WebSocket的持久化連接,它可以減少HTTP請求的數(shù)量,從而減少了網(wǎng)絡(luò)負(fù)載。
WebSocket的劣勢包括:
需要瀏覽器和服務(wù)器都支持: WebSocket是一種相對新的技術(shù),需要瀏覽器和服務(wù)器都支持。一些舊的瀏覽器和服務(wù)器可能不支持WebSocket。
需要額外的開銷: WebSocket需要在服務(wù)器上維護(hù)長時(shí)間的連接,這需要額外的開銷,包括內(nèi)存和CPU。
安全問題: 由于WebSocket允許服務(wù)器主動向客戶端發(fā)送數(shù)據(jù),可能會存在安全問題。服務(wù)器必須保證只向合法的客戶端發(fā)送數(shù)據(jù)。
二、 WebSocket的基本概念2.1 WebSocket的協(xié)議WebSocket 協(xié)議是一種基于TCP的協(xié)議,用于在客戶端和服務(wù)器之間建立持久連接,并且可以在這個(gè)連接上實(shí)時(shí)地交換數(shù)據(jù)。WebSocket協(xié)議有自己的握手協(xié)議,用于建立連接,也有自己的數(shù)據(jù)傳輸格式。
當(dāng)客戶端發(fā)送一個(gè) WebSocket 請求時(shí),服務(wù)器將發(fā)送一個(gè)協(xié)議響應(yīng)以確認(rèn)請求。在握手期間,客戶端和服務(wù)器將協(xié)商使用的協(xié)議版本、支持的子協(xié)議、支持的擴(kuò)展選項(xiàng)等。一旦握手完成,連接將保持打開狀態(tài),客戶端和服務(wù)器就可以在連接上實(shí)時(shí)地傳遞數(shù)據(jù)。
WebSocket 協(xié)議使用的是雙向數(shù)據(jù)傳輸,即客戶端和服務(wù)器都可以在任意時(shí)間向?qū)Ψ桨l(fā)送數(shù)據(jù),而不需要等待對方的請求。它支持二進(jìn)制數(shù)據(jù)和文本數(shù)據(jù),可以自由地在它們之間進(jìn)行轉(zhuǎn)換。
總之,WebSocket協(xié)議是一種可靠的、高效的、雙向的、持久的通信協(xié)議,它適用于需要實(shí)時(shí)通信的Web應(yīng)用程序,如在線游戲、實(shí)時(shí)聊天等。
2.2 WebSocket的生命周期WebSocket 生命周期描述了 WebSocket 連接從創(chuàng)建到關(guān)閉的過程。一個(gè) WebSocket 連接包含以下四個(gè)主要階段:
連接建立階段(Connection Establishment): 在這個(gè)階段,客戶端和服務(wù)器之間的 WebSocket 連接被建立??蛻舳税l(fā)送一個(gè) WebSocket 握手請求,服務(wù)器響應(yīng)一個(gè)握手響應(yīng),然后連接就被建立了。
連接開放階段(Connection Open): 在這個(gè)階段,WebSocket 連接已經(jīng)建立并開放,客戶端和服務(wù)器可以在連接上互相發(fā)送數(shù)據(jù)。
連接關(guān)閉階段(Connection Closing): 在這個(gè)階段,一個(gè) WebSocket 連接即將被關(guān)閉。它可以被客戶端或服務(wù)器發(fā)起,通過發(fā)送一個(gè)關(guān)閉幀來關(guān)閉連接。
連接關(guān)閉完成階段(Connection Closed): 在這個(gè)階段,WebSocket 連接已經(jīng)完全關(guān)閉??蛻舳撕头?wù)器之間的任何交互都將無效。
“
需要注意的是,WebSocket 連接在任何時(shí)候都可能關(guān)閉,例如網(wǎng)絡(luò)故障、服務(wù)器崩潰等情況都可能導(dǎo)致連接關(guān)閉。因此,需要及時(shí)處理 WebSocket 連接關(guān)閉的事件,以確保應(yīng)用程序的可靠性和穩(wěn)定性。
下面是一個(gè)簡單的 WebSocket 生命周期示意圖:

在這個(gè)示意圖中,客戶端向服務(wù)器發(fā)送一個(gè) WebSocket 握手請求,服務(wù)器響應(yīng)一個(gè)握手響應(yīng),連接就被建立了。一旦連接建立,客戶端和服務(wù)器就可以在連接上互相發(fā)送數(shù)據(jù),直到其中一方發(fā)送一個(gè)關(guān)閉幀來關(guān)閉連接。在關(guān)閉幀被接收后,連接就會被關(guān)閉,WebSocket 連接關(guān)閉完成。
2.3 WebSocket的消息格式WebSocket 的消息格式與 HTTP 請求和響應(yīng)的消息格式有所不同。WebSocket 的消息格式可以是文本或二進(jìn)制數(shù)據(jù),并且 WebSocket 消息的傳輸是在一個(gè)已經(jīng)建立的連接上進(jìn)行的,因此不需要再進(jìn)行 HTTP 請求和響應(yīng)的握手操作。
WebSocket 消息格式由兩個(gè)部分組成:消息頭和消息體。
消息頭包含以下信息:
FIN: 表示這是一條完整的消息,一般情況下都是1。
RSV1、RSV2、RSV3: 暫時(shí)沒有使用,一般都是0。
Opcode: 表示消息的類型,包括文本消息、二進(jìn)制消息等。
Mask: 表示消息是否加密。
Payload length: 表示消息體的長度。
Masking key: 僅在消息需要加密時(shí)出現(xiàn),用于對消息進(jìn)行解密。
消息體就是實(shí)際傳輸?shù)臄?shù)據(jù),可以是文本或二進(jìn)制數(shù)據(jù)。
2.4 WebSocket的APIWebSocket API 是用于在 Web 應(yīng)用程序中創(chuàng)建和管理 WebSocket 連接的接口集合。WebSocket API 由瀏覽器原生支持,無需使用額外的 JavaScript 庫或框架,可以直接在 JavaScript 中使用。
下面是一些常用的 WebSocket API:
WebSocket 構(gòu)造函數(shù): WebSocket 構(gòu)造函數(shù)用于創(chuàng)建 WebSocket 對象。它接受一個(gè) URL 作為參數(shù),表示要連接的 WebSocket 服務(wù)器的地址。例如:
let ws = new WebSocket('ws://example.com/ws');
WebSocket.send() 方法: WebSocket.send() 方法用于向服務(wù)器發(fā)送數(shù)據(jù)。它接受一個(gè)參數(shù),表示要發(fā)送的數(shù)據(jù)。數(shù)據(jù)可以是字符串、Blob 對象或 ArrayBuffer 對象。例如:
ws.send('Hello, server!');
WebSocket.onopen 事件: WebSocket.onopen 事件在 WebSocket 連接成功建立時(shí)觸發(fā)。例如:
ws.onopen = function() { console.log('WebSocket 連接已經(jīng)建立。');};
WebSocket.onmessage 事件: WebSocket.onmessage 事件在接收到服務(wù)器發(fā)送的消息時(shí)觸發(fā)。它的 event 對象包含一個(gè) data 屬性,表示接收到的數(shù)據(jù)。例如:
ws.onmessage = function(event) { console.log('收到服務(wù)器消息:', event.data);};
WebSocket.onerror 事件: WebSocket.onerror 事件在 WebSocket 連接出現(xiàn)錯(cuò)誤時(shí)觸發(fā)。例如:
ws.onerror = function(event) { console.error('WebSocket 連接出現(xiàn)錯(cuò)誤:', event);};
WebSocket.onclose 事件: WebSocket.onclose 事件在 WebSocket 連接被關(guān)閉時(shí)觸發(fā)。例如:
ws.onclose = function() { console.log('WebSocket 連接已經(jīng)關(guān)閉。');};
以上是一些常用的 WebSocket API。
三、 在Java中使用WebSocket依賴:
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/websocket")
public class WebSocketServer {
@OnOpen
public void onOpen(Session session) {
System.out.println("Connection opened: " + session.getId());
sessions.add(session);
}
@OnMessage
public void onMessage(Session session, String message) throws IOException {
System.out.println("Received message: " + message);
session.getBasicRemote().sendText("Server received: " + message);
}
@OnClose
public void onClose(Session session) {
System.out.println("Connection closed: " + session.getId());
sessions.remove(session);
}
private static final Set<Session> sessions = Collections.synchronizedSet(new HashSet<Session>());
}