最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

WebSocket超細致完整用法舉例講解(含原理+前端+后端+實戰(zhàn)案例+避坑指南)

 更新時間:2026年05月12日 10:29:55   作者:不吃香菜567  
websocket是一種網(wǎng)絡通訊協(xié)議,我們之前可能也學過,其他的一些協(xié)議,比如偏底層的TCP,UDP,而應用層的協(xié)議,用的最多的還是HTTP協(xié)議,這篇文章主要介紹了WebSocket超細致完整用法的相關(guān)資料,需要的朋友可以參考下

前言

你想要透徹掌握 WebSocket 的完整用法,我會從核心原理、前后端完整代碼、使用場景、核心 API、心跳?;?、常見問題等維度,一步步細致講解,內(nèi)容通俗易懂,學完就能直接落地開發(fā)。

一、WebSocket 核心認知(必懂,理解了用法才通透)

1. WebSocket 是什么?

WebSocket 是 HTML5 新增的一種「全雙工、持久化」的網(wǎng)絡通信協(xié)議,協(xié)議標識是 ws://(明文)和 wss://(加密,推薦生產(chǎn)環(huán)境用),是 HTTP 協(xié)議的補充和升級。

2. 為什么需要 WebSocket?HTTP 協(xié)議的痛點

HTTP 協(xié)議是 「單工 / 半雙工」、「短連接」、「無狀態(tài)」 的通信模式,有 2 個致命痛點:

  • ? 通信方向:只能由客戶端主動發(fā)起請求 → 服務端被動響應,服務端永遠不能主動給客戶端發(fā)消息;
  • ? 連接狀態(tài):每次請求響應完成后,TCP 連接就斷開,下次通信需要重新建立連接,開銷大;

這就導致 HTTP 無法實現(xiàn)「實時通信」場景(比如聊天、股票行情、掃碼登錄、消息推送),之前只能用「輪詢 / 長輪詢」曲線救國,但效率極低、資源浪費嚴重。

3. WebSocket 核心優(yōu)勢(對比 HTTP 碾壓級)

全雙工通信:連接建立后,客戶端 ↔ 服務端 雙向平等通信,雙方都可以主動向?qū)Ψ桨l(fā)送消息,無需誰請求誰;? 持久連接:一次握手成功后,TCP 連接會一直保持,直到主動斷開,沒有頻繁的連接建立 / 銷毀開銷;? 輕量級數(shù)據(jù)傳輸:通信頭信息極小,數(shù)據(jù)傳輸效率高;? 無同源限制:客戶端和服務端建立連接時,不受瀏覽器同源策略的限制;? 基于 TCP:底層復用 TCP 協(xié)議,穩(wěn)定性高、傳輸可靠。

4. WebSocket 與 HTTP 的關(guān)系(重點,易混淆)

WebSocket 不是替代 HTTP,而是 基于 HTTP 完成握手,之后脫離 HTTP 獨立通信,二者關(guān)系:

  1. 客戶端發(fā)起 WebSocket 連接時,發(fā)送的是 HTTP 協(xié)議的請求(叫「握手請求」);
  2. 服務端收到請求后,返回 HTTP 101 狀態(tài)碼(協(xié)議切換),完成「握手」;
  3. 握手成功后,雙方的通信就不再走 HTTP 協(xié)議,而是走純 WebSocket 協(xié)議,全雙工傳輸數(shù)據(jù)。

二、WebSocket 完整通信流程(極簡版,先建立全局認知)

不管前端用原生 JS、Vue/React,后端用 Java/Node/PHP/Python,所有 WebSocket 的通信流程完全一致,只有3 個核心步驟,記住這個流程,所有用法都圍繞它展開:

核心三步流程(通用,重中之重)

  1. 建立連接(握手):客戶端主動發(fā)起連接請求,服務端同意,雙方建立持久的 TCP 連接;
  2. 數(shù)據(jù)通信(雙工):連接成功后,客戶端 ↔ 服務端,雙方都能主動發(fā)消息、收消息,互相通信;
  3. 斷開連接(銷毀):任意一方主動關(guān)閉連接,或網(wǎng)絡異常導致連接斷開,釋放資源。

三、前端 WebSocket 用法(原生 JS,最全 API,無框架依賴,通用所有前端項目)

前端是 WebSocket 最核心的使用端,瀏覽器原生內(nèi)置了 WebSocket 對象,無需引入任何依賴,直接使用,語法完全標準化,Vue/React/ 小程序里的用法和原生 JS 一致,只是把代碼放到對應的生命周期即可。

1. 前端完整代碼(可直接復制運行,含所有核心功能)

// 1. 創(chuàng)建WebSocket實例,建立連接(核心)
// 語法:new WebSocket(協(xié)議地址)
// 本地測試:ws://localhost:8080  生產(chǎn)加密:wss://你的域名:端口
let ws = new WebSocket('ws://localhost:8080');

// -------------------------- 2. 核心事件:4個必用事件(監(jiān)聽連接狀態(tài)+收發(fā)消息) --------------------------
/**
 * ? 事件1:onopen - 連接成功(握手成功)觸發(fā)【必寫】
 * 連接建立后,只會觸發(fā)1次,適合做:初始化、登錄鑒權(quán)、發(fā)送首次請求等
 */
ws.onopen = function () {
  console.log('? WebSocket 連接成功!');
  // 連接成功后,客戶端主動給服務端發(fā)消息(send方法)
  ws.send('哈嘍,服務端,我是客戶端,連接成功啦!');
};

/**
 * ? 事件2:onmessage - 收到服務端的消息時觸發(fā)【核心必寫】
 * 只要服務端給客戶端發(fā)消息,這個事件就會觸發(fā),實時接收消息
 * event.data:固定屬性,拿到服務端發(fā)送的「消息內(nèi)容」(字符串格式)
 */
ws.onmessage = function (event) {
  console.log('?? 收到服務端消息:', event.data);
  // 業(yè)務處理:比如渲染聊天消息、更新實時數(shù)據(jù)、處理推送通知等
  // 如果服務端發(fā)的是JSON對象,需要解析:const data = JSON.parse(event.data);
};

/**
 * ? 事件3:onclose - 連接關(guān)閉時觸發(fā)【必寫】
 * 觸發(fā)場景:主動關(guān)閉連接、網(wǎng)絡斷開、服務端下線、超時等
 * event.code:關(guān)閉狀態(tài)碼,event.reason:關(guān)閉原因
 */
ws.onclose = function (event) {
  console.log('? WebSocket 連接關(guān)閉', event.code, event.reason);
  // 業(yè)務處理:提示用戶、清空實時數(shù)據(jù)、嘗試重連等
};

/**
 * ? 事件4:onerror - 連接發(fā)生錯誤時觸發(fā)【必寫】
 * 觸發(fā)場景:地址錯誤、服務端未啟動、網(wǎng)絡異常、跨域配置錯誤等
 * 錯誤發(fā)生后,大概率會緊接著觸發(fā) onclose 事件
 */
ws.onerror = function (error) {
  console.error('? WebSocket 連接異常:', error);
};

// -------------------------- 3. 核心方法:2個必用方法(主動發(fā)消息+主動關(guān)連接) --------------------------
/**
 * ? 方法1:ws.send(msg) - 客戶端主動發(fā)送消息給服務端【核心必寫】
 * 入?yún)?msg:必須是「字符串類型」?。?!
 * 注意:如果要發(fā)送對象/數(shù)組,必須先轉(zhuǎn)JSON:JSON.stringify({name: '張三', age: 20})
 */
// 示例:發(fā)送JSON對象
const userInfo = { userId: 1001, userName: '前端小菜雞' };
ws.send(JSON.stringify(userInfo));

/**
 * ? 方法2:ws.close() - 客戶端主動關(guān)閉連接【必寫】
 * 觸發(fā)場景:頁面關(guān)閉、用戶退出、不需要實時通信時(比如離開聊天頁)
 * 調(diào)用后,會觸發(fā)自身的 onclose 事件,服務端也會收到關(guān)閉通知
 */
// 比如:頁面銷毀時關(guān)閉連接(Vue的beforeDestroy、React的componentWillUnmount)
window.addEventListener('unload', () => {
  ws.close();
  console.log('?? 客戶端主動關(guān)閉連接');
});

// -------------------------- 4. 核心屬性:1個常用屬性 --------------------------
/**
 * ? readyState - 查看當前WebSocket的「連接狀態(tài)」【常用】
 * 有4個固定值,只讀,不能修改:
 * 0: CONNECTING - 正在連接中(剛new出來,還沒握手)
 * 1: OPEN       - 連接成功(可以正常收發(fā)消息,最常用)
 * 2: CLOSING    - 正在關(guān)閉中(調(diào)用了close,還沒完全斷開)
 * 3: CLOSED     - 連接已關(guān)閉(無法收發(fā)消息)
 */
console.log('當前連接狀態(tài):', ws.readyState);
// 業(yè)務中常用:發(fā)送消息前判斷連接是否正常,避免報錯
if (ws.readyState === 1) {
  ws.send('確保連接正常時發(fā)送的消息');
}

2. 前端核心注意事項(避坑重點,90% 的前端問題都在這里)

  • send 方法的入?yún)⑾拗?/strong>:ws.send() 只能傳字符串!如果要傳對象 / 數(shù)組 / 數(shù)字,必須用 JSON.stringify() 轉(zhuǎn)成字符串,服務端收到后再用 JSON.parse() 解析,反之同理。
  • 連接狀態(tài)判斷:發(fā)送消息前,一定要先判斷 ws.readyState === 1,如果連接未建立 / 已關(guān)閉,直接 send 會報錯。
  • 頁面銷毀必關(guān)連接:單頁應用(Vue/React)中,離開當前頁面時,必須調(diào)用 ws.close() 關(guān)閉連接,否則會造成「連接泄漏」,多個無效連接占用資源。
  • 異常處理onerror 事件只是「錯誤監(jiān)聽」,不能阻止錯誤發(fā)生,錯誤后大概率會觸發(fā) onclose,可以在 onclose 中做「重連邏輯」。

四、后端 WebSocket 用法(多語言極簡實戰(zhàn)案例,夠用 + 能用)

WebSocket 是客戶端 - 服務端雙向協(xié)議,必須有服務端配合才能運行,后端的核心職責是:啟動 WebSocket 服務、監(jiān)聽客戶端連接、接收客戶端消息、主動給客戶端發(fā)消息、關(guān)閉連接。

這里提供 3 種主流后端語言的極簡完整案例,全部可直接復制運行,代碼極簡無冗余,適合入門和實戰(zhàn),也是企業(yè)開發(fā)中最常用的方案:

方案 1:Node.js 實現(xiàn) WebSocket 服務(最簡單,零配置,推薦入門測試)

Node.js 有一個超好用的第三方包 ws,專門處理 WebSocket,輕量、高效、文檔友好,無需配置任何服務器,裝包即運行。

步驟 1:初始化 + 安裝依賴

# 新建文件夾,初始化
npm init -y
# 安裝ws包
npm install ws

步驟 2:完整服務端代碼(server.js)

const WebSocket = require('ws');
// 創(chuàng)建WebSocket服務,監(jiān)聽8080端口
const wss = new WebSocket.Server({ port: 8080 });

console.log('? Node.js WebSocket服務啟動成功,監(jiān)聽端口:8080');

// 監(jiān)聽「客戶端連接」事件:有客戶端連上來就觸發(fā)
wss.on('connection', (ws) => {
  console.log('?? 有一個客戶端成功連接');

  // 監(jiān)聽「客戶端發(fā)送的消息」事件:接收客戶端消息
  ws.on('message', (msg) => {
    console.log('?? 收到客戶端消息:', msg.toString());
    // 服務端主動給「當前連接的客戶端」發(fā)消息
    ws.send(`我收到你的消息啦:${msg.toString()}`);
    
    // 【進階】廣播消息:給「所有連接的客戶端」發(fā)消息(比如群聊)
    wss.clients.forEach(client => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(`廣播:有客戶端說:${msg.toString()}`);
      }
    });
  });

  // 監(jiān)聽「客戶端斷開連接」事件
  ws.on('close', () => {
    console.log('?? 客戶端斷開連接');
  });

  // 監(jiān)聽「連接錯誤」事件
  ws.on('error', (err) => {
    console.error('? 連接異常:', err);
  });
});

運行

node server.js

此時前端連接 ws://localhost:8080 即可正常通信!

方案 2:Java 實現(xiàn) WebSocket 服務(SpringBoot 主流方案,企業(yè)級)

Java 開發(fā)中,SpringBoot 是絕對主流,SpringBoot 2.x 之后內(nèi)置了 WebSocket 支持,無需引入額外依賴,配置極簡,適合后端 Java 開發(fā)同學。

步驟 1:核心配置類(開啟 WebSocket)

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

@Configuration
@EnableWebSocket // 開啟WebSocket支持
public class WebSocketConfig implements WebSocketConfigurer {
    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
        // 配置WebSocket地址:ws://localhost:8080/ws
        registry.addHandler(new MyWebSocketHandler(), "/ws")
                .setAllowedOrigins("*"); // 允許所有跨域(生產(chǎn)環(huán)境可指定域名)
    }
}

步驟 2:核心處理器(處理連接 + 收發(fā)消息)

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

public class MyWebSocketHandler extends TextWebSocketHandler {
    // 存儲所有連接的客戶端
    private static final CopyOnWriteArraySet<WebSocketSession> sessions = new CopyOnWriteArraySet<>();

    // 連接成功觸發(fā)
    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        sessions.add(session);
        System.out.println("? 客戶端連接成功,當前在線數(shù):" + sessions.size());
    }

    // 接收客戶端消息觸發(fā)
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        String msg = message.getPayload();
        System.out.println("?? 收到客戶端消息:" + msg);
        // 服務端給客戶端發(fā)消息
        session.sendMessage(new TextMessage("服務端已收到:" + msg));
    }

    // 連接關(guān)閉觸發(fā)
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
        sessions.remove(session);
        System.out.println("? 客戶端斷開連接,當前在線數(shù):" + sessions.size());
    }
}

運行 SpringBoot 項目,前端連接 ws://localhost:8080/ws 即可通信。

方案 3:Python 實現(xiàn) WebSocket 服務(FastAPI 極簡方案)

Python 主流的 WebSocket 方案是 FastAPI(原生支持),代碼極簡,適合 Python 后端開發(fā)同學:

from fastapi import FastAPI, WebSocket
from fastapi.responses import HTMLResponse

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept() # 接受客戶端連接
    print("? 客戶端連接成功")
    while True:
        data = await websocket.receive_text() # 接收客戶端消息
        print(f"?? 收到消息:{data}")
        await websocket.send_text(f"服務端已收到:{data}") # 發(fā)送消息給客戶端

運行后,前端連接 ws://localhost:8000/ws 即可通信。

五、WebSocket 心跳機制 & 斷線重連(實戰(zhàn)必做,重中之重?。?/h2>

這是 WebSocket 生產(chǎn)環(huán)境必須實現(xiàn)的功能,也是很多初學者學完基礎(chǔ)用法后,遇到的最大痛點:為什么我的 WebSocket 連接會莫名斷開?為什么網(wǎng)絡恢復后連不上?

1. 為什么需要「心跳?;?+ 斷線重連」?

WebSocket 是持久連接,但在實際生產(chǎn)環(huán)境中,有很多「隱形斷開」的場景:

  • 服務器有超時機制:大部分服務器(Nginx/Tomcat/Node)會主動斷開「長時間無數(shù)據(jù)傳輸」的連接(比如 30 秒 / 60 秒);
  • 網(wǎng)絡問題:用戶切換網(wǎng)絡(WiFi→4G)、路由器重啟、網(wǎng)絡波動,會導致連接斷開,但客戶端不知道;
  • 防火墻 / 代理:中間層設備會主動清理空閑連接,導致連接異常斷開。

這種斷開是「靜默斷開」:客戶端的 onclose 事件不會立刻觸發(fā),客戶端以為連接還在,發(fā)消息時才發(fā)現(xiàn)失敗,體驗極差。

2. 心跳機制原理(簡單易懂)

心跳 = 客戶端和服務端之間的「定時問候」,證明對方還活著。

  • 規(guī)則:客戶端每隔固定時間(比如 10 秒)給服務端發(fā)送一個「心跳消息」(比如:ping);
  • 服務端收到心跳消息后,必須回復一個「心跳響應」(比如:pong);
  • 意義:只要能正常收發(fā)心跳,就證明連接是存活的;如果收不到響應,就判定為連接斷開,觸發(fā)重連。

3. 前端完整實現(xiàn)「心跳 + 斷線重連」(可直接復制,生產(chǎn)可用)

在之前的原生前端代碼基礎(chǔ)上,新增心跳和重連邏輯,無侵入,不影響原有業(yè)務

let ws = null;
let heartBeatTimer = null; // 心跳定時器
let reconnectTimer = null; // 重連定時器
const wsUrl = 'ws://localhost:8080';
const heartBeatInterval = 10000; // 心跳間隔:10秒
const reconnectInterval = 3000; // 重連間隔:3秒

// 初始化WebSocket連接
function initWebSocket() {
  ws = new WebSocket(wsUrl);
  
  ws.onopen = function () {
    console.log('? 連接成功');
    startHeartBeat(); // 連接成功,啟動心跳
    ws.send('連接成功,請求登錄');
  };

  ws.onmessage = function (event) {
    const msg = event.data;
    console.log('?? 收到消息:', msg);
    // 收到服務端的pong,說明心跳正常,無需處理,重置定時器即可
    if (msg === 'pong') return;
    // 業(yè)務消息處理...
  };

  ws.onclose = function () {
    console.log('? 連接關(guān)閉,準備重連');
    stopHeartBeat(); // 關(guān)閉心跳
    startReconnect(); // 啟動重連
  };

  ws.onerror = function () {
    console.error('? 連接異常');
    stopHeartBeat();
    startReconnect();
  };
}

// 啟動心跳:定時發(fā)送ping
function startHeartBeat() {
  heartBeatTimer = setInterval(() => {
    if (ws.readyState === 1) {
      ws.send('ping'); // 發(fā)送心跳包
    } else {
      stopHeartBeat();
    }
  }, heartBeatInterval);
}

// 停止心跳
function stopHeartBeat() {
  clearInterval(heartBeatTimer);
  heartBeatTimer = null;
}

// 啟動重連:失敗后每隔3秒重試一次
function startReconnect() {
  if (reconnectTimer) return; // 避免重復創(chuàng)建定時器
  reconnectTimer = setInterval(() => {
    console.log('?? 嘗試重連...');
    initWebSocket();
    // 重連成功后,清除重連定時器
    if (ws.readyState === 1) {
      clearInterval(reconnectTimer);
      reconnectTimer = null;
    }
  }, reconnectInterval);
}

// 頁面加載時初始化
window.onload = initWebSocket;
// 頁面關(guān)閉時銷毀
window.onunload = function () {
  ws.close();
  stopHeartBeat();
  clearInterval(reconnectTimer);
};

? 服務端配合:只需要在收到 ping 消息時,回復 pong 即可,無需額外邏輯,非常簡單。

六、WebSocket 適用場景 & 不適用場景(選型必看)

適合用 WebSocket 的場景(實時性要求高,雙向通信)

這是 WebSocket 的主場,這些場景用 HTTP 實現(xiàn)會非常低效,甚至無法實現(xiàn):

  • 即時通訊:在線聊天、客服對話、群聊、彈幕;
  • 實時數(shù)據(jù)展示:股票行情、區(qū)塊鏈價格、游戲?qū)崟r數(shù)據(jù)、監(jiān)控面板;
  • 消息推送:系統(tǒng)通知、訂單狀態(tài)變更、掃碼登錄、物流軌跡;
  • 協(xié)作工具:在線文檔協(xié)同編輯、多人白板、在線會議;
  • 高頻交互場景:游戲、直播連麥、實時投票。

不適合用 WebSocket 的場景(別濫用)

WebSocket 是「持久連接」,會占用服務端資源,以下場景用 HTTP 更合適:

  • 普通數(shù)據(jù)查詢:比如查詢用戶信息、商品列表、歷史訂單(一次性請求,無需實時);
  • 靜態(tài)資源請求:圖片、視頻、CSS/JS 文件;
  • 低頻交互場景:比如表單提交、評論發(fā)布(提交一次就結(jié)束);
  • 對連接數(shù)要求極高的場景:比如百萬級靜態(tài)頁面訪問(HTTP 更輕量)。

七、WebSocket 常見面試題 & 高頻問題(查漏補缺)

Q1:WebSocket 和 HTTP 的區(qū)別?

答:核心 3 點:

  • 通信方式:HTTP 是半雙工(客戶端請求→服務端響應),WebSocket 是全雙工(雙向主動發(fā)消息);
  • 連接狀態(tài):HTTP 是短連接(請求完斷開),WebSocket 是長連接(一次握手,持久通信);
  • 發(fā)起方式:HTTP 是客戶端單向發(fā)起,WebSocket 是客戶端發(fā)起握手,之后雙向平等通信。

Q2:WebSocket 有同源限制嗎?

答:客戶端連接時,不受瀏覽器同源策略限制(可以跨域連接任意服務端),但服務端可以通過配置,限制允許的客戶端域名,防止非法連接。

Q3:WebSocket 如何實現(xiàn)鑒權(quán)?

答:主流 2 種方式(生產(chǎn)必用,防止非法連接):

  • 連接時在 URL 拼接 token:new WebSocket('ws://localhost:8080?token=xxx'),服務端拿到 token 驗證用戶身份;
  • 連接成功后,客戶端通過 send 發(fā)送用戶名 / 密碼 /token,服務端驗證后再允許通信。

Q4:WebSocket 支持二進制傳輸嗎?

答:支持!ws.send() 不僅可以傳字符串,還可以傳 BlobArrayBuffer 二進制數(shù)據(jù),適合傳輸圖片、文件等。

總結(jié)(核心知識點速記,看完就忘不掉)

  • WebSocket 是全雙工、持久化的通信協(xié)議,解決 HTTP 無法實時通信的痛點;
  • 核心流程:建立連接 → 雙向通信 → 斷開連接,前后端通用;
  • 前端核心:new WebSocket() 創(chuàng)建實例,4 個事件(onopen/onmessage/onclose/onerror)+ 2 個方法(send/close);
  • 后端核心:監(jiān)聽連接、接收消息、發(fā)送消息、處理斷開,多語言都有成熟方案;
  • 生產(chǎn)必做:心跳保活 + 斷線重連,解決靜默斷開問題;
  • 適用場景:實時通信、消息推送、高頻交互,別濫用在普通查詢場景。

到此這篇關(guān)于WebSocket超細致完整用法的文章就介紹到這了,更多相關(guān)WebSocket完整用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

连城县| 会同县| 桓台县| 东辽县| 福鼎市| 嵩明县| 贵阳市| 车险| 蛟河市| 汉中市| 囊谦县| 烟台市| 山东省| 黔江区| 曲水县| 泗水县| 同心县| 岳西县| 怀来县| 蓬安县| 合水县| 江达县| 会泽县| 北碚区| 华容县| 南投县| 肇源县| 临海市| 深泽县| 离岛区| 乌海市| 博兴县| 阳高县| 屯昌县| 肥乡县| 肇庆市| 新疆| 饶平县| 顺义区| 宁城县| 中超|