首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

WebSocket 協議入門:從原理到 Java 實戰的全雙工通信實現

     編輯:Java 綜合教學

WebSocket 協議入門:從原理到 Java 實戰的全雙工通信實現

傳統 HTTP 請求-回應模式無法滿足伺服器主動推送需求,WebSocket 作為基於 TCP 的應用層全雙工協議 (RFC 6455),解決了這一痛點。本文涵蓋協議本質、適用場景、瀏覽器/伺服器支援現況,並提供基於 Tomcat 8 + JSR 356 的完整 Java 實戰代碼。

一、WebSocket 協議本質

  • 全雙工:客戶端與伺服器可獨立雙向發送資料,無需輪詢
  • 基於 TCP:應用層協議,握手階段借用 HTTP Upgrade 機制
  • 輕量幀:建立連線後,資料幀開銷極小 (最小 2 位元組)
  • 源安全:採用瀏覽器同源策略,握手攜帶 Origin 標頭驗證

握手流程:

  1. 客戶端發送 HTTP GET 請求,攜帶 Upgrade: websocket, Connection: Upgrade, Sec-WebSocket-Key
  2. 伺服器回應 101 Switching Protocols,攜帶 Sec-WebSocket-Accept (Key 加密驗證)
  3. 協議升級完成,雙方進入 WebSocket 幀傳輸階段

二、適用場景與支援現況

場景傳統方案WebSocket 方案
伺服器主動推送通知輪詢/長輪詢/Comet直接推送,零延遲
即時聊天/協作編輯頻繁 AJAX 請求持久連線,雙向即時
股票/行情即時推送定時拉取伺服器主動廣播
遊戲狀態同步短輪詢低延遲雙向通道

瀏覽器支援:IE 10+、Chrome 4+、Firefox 4+、Safari 5+、Opera 12+ — 現代瀏覽器全支援。
伺服器支援:Tomcat 7.0.47+、Jetty 9+、Netty、Undertow、Node.js (ws/socket.io) 等。

三、Java 實戰:Tomcat 8 + JSR 356 (javax.websocket)

3.1 依賴引入

<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope> <!-- Tomcat 內建實現 -->
</dependency>

3.2 伺服器端點

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

@ServerEndpoint("/websocket")
public class TestWebSocket {
    
    @OnOpen
    public void onOpen(Session session) {
        System.out.println("客戶端連線:" + session.getId());
    }
    
    @OnMessage
    public void onMessage(String message, Session session) 
            throws IOException, InterruptedException {
        System.out.println("收到訊息:" + message);
        
        // 立即回覆
        session.getBasicRemote().sendText("伺服器收到:" + message);
        
        // 模擬伺服器主動推送 3 條訊息,間隔 5 秒
        for (int i = 0; i < 3; i++) {
            Thread.sleep(5000);
            session.getBasicRemote().sendText("主動推送 #" + (i+1) + ":" + System.currentTimeMillis());
        }
        
        session.getBasicRemote().sendText("推送結束");
    }
    
    @OnClose
    public void onClose(Session session, CloseReason reason) {
        System.out.println("連線關閉:" + reason.getReasonPhrase());
    }
    
    @OnError
    public void onError(Session session, Throwable throwable) {
        System.err.println("錯誤:" + throwable.getMessage());
    }
}

3.3 前端頁面

<!DOCTYPE html>
<html>
<head><title>WebSocket 測試</title></head>
<body>
    <button onclick="connect()">連線</button>
    <button onclick="send()">發送訊息</button>
    <button onclick="close()">斷開</button>
    <div id="log"></div>
    
    <script>
    var ws;
    function connect() {
        ws = new WebSocket('ws://localhost:8080/TestWebSocket/websocket');
        ws.onopen = () => log('連線已建立');
        ws.onmessage = (e) => log('收到:' + e.data);
        ws.onclose = () => log('連線關閉');
        ws.onerror = (e) => log('錯誤:' + e);
    }
    function send() { ws.send('Hello from ' + new Date()); }
    function close() { ws.close(); }
    function log(msg) { 
        document.getElementById('log').innerHTML += '<br>' + msg; 
    }
    </script>
</body>
</html>

四、WebSocket 與 HTTP/TCP 關係圖譜

TCP (傳輸層)
  ├─ HTTP/1.1 (應用層) —— 請求/回應,半雙工
  ├─ HTTP/2 (應用層) —— 多路複用,仍為請求/回應語義
  └─ WebSocket (應用層) —— 全雙工,握手借用 HTTP Upgrade

關鍵點:WebSocket 獨立於 HTTP,僅握手階段借用 HTTP 協議升級機制,建立連線後完全脫離 HTTP 語義,直接在 TCP 上傳輸自定義幀。

五、生產環境關鍵考量

  • 心跳機制:防止防火牆/代理斷開閒置連線 (Ping/Pong 幀)
  • 重連策略:指數退避重連,避免連線風暴
  • 訊息幂等性:網路不穩可能導致重複投遞,業務層需去重
  • 叢集支援:多實例部署需引入 Redis Pub/Sub 或 Kafka 做訊息廣播
  • 安全性:WSS (WebSocket over TLS)、Origin 驗證、認證授權
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved