前端實現雙工通信(全雙工或半雙工)的常見方案及詳細實現如下:
一、WebSocket(全雙工)
原理:基于 TCP 的持久化協議,客戶端與服務端建立雙向通信通道,支持實時雙向數據傳輸。
// 客戶端(瀏覽器)
const socket = new WebSocket('ws://your-server:port');// 監聽消息
socket.onmessage = (event) => {console.log('收到消息:', event.data);
};// 發送消息
socket.send('Hello Server');// 服務端(Node.js示例,使用 ws 庫)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
wss.on('connection', (ws) => {ws.on('message', (message) => {console.log('收到客戶端消息:', message);ws.send('Hello Client');});
});
適用場景:實時聊天、在線游戲、協同編輯等高頻雙向通信場景。
優點:低延遲、高效、支持二進制數據傳輸。
缺點:需服務端主動支持 WebSocket 協議。
二、Server-Sent Events (SSE) + HTTP(半雙工)
原理:SSE 允許服務器單向推送數據到客戶端,客戶端通過普通 HTTP 請求發送數據。
// 客戶端接收服務端推送
const eventSource = new EventSource('/sse-endpoint');
eventSource.onmessage = (e) => {console.log('收到服務端推送:', e.data);
};// 客戶端發送數據(通過 Fetch API)
fetch('/send-data', {method: 'POST',body: JSON.stringify({ msg: 'Hello Server' })
});// 服務端(Node.js示例)
app.get('/sse-endpoint', (req, res) => {res.setHeader('Content-Type', 'text/event-stream');setInterval(() => {res.write(`data: ${Date.now()}\n\n`); // 推送數據}, 1000);
});app.post('/send-data', (req, res) => {console.log('收到客戶端數據:', req.body.msg);res.sendStatus(200);
});
適用場景:股票行情、新聞推送等以服務端推送為主的場景。
優點:簡單、支持自動重連、兼容 HTTP 協議。
缺點:客戶端到服務端需額外 HTTP 請求,非真正全雙工。
三、長輪詢(Long Polling,半雙工模擬)
原理:客戶端發起請求后,服務端保持連接直到有數據或超時,客戶端收到響應后立即發起新請求。
// 客戶端輪詢
function longPoll() {fetch('/polling-endpoint').then(res => res.json()).then(data => {console.log('收到數據:', data);longPoll(); // 遞歸調用維持連接});
}
longPoll();// 服務端(Node.js示例)
const messages = [];
app.get('/polling-endpoint', (req, res) => {// 等待新消息或超時(如30秒)const waitForMessage = (resolve) => {if (messages.length > 0) {res.json(messages.shift());} else {setTimeout(() => waitForMessage(resolve), 30000);}};waitForMessage();
});
適用場景:兼容性要求高、低頻通信場景。
優點:兼容所有瀏覽器。
缺點:高延遲、服務端資源消耗大。
四、HTTP/2 Server Push(半雙工)
原理:HTTP/2 允許服務端主動推送資源,但需配合客戶端請求使用。
// 服務端(Node.js,使用 http2 模塊)
const http2 = require('http2');
const server = http2.createSecureServer({ cert, key });
server.on('stream', (stream, headers) => {if (headers[':path'] === '/') {stream.pushStream({ ':path': '/api/data' }, (err, pushStream) => {pushStream.respond({ ':status': 200 });pushStream.end(JSON.stringify({ data: 'Pushed Data' }));});stream.end('Main Response');}
});
適用場景:預加載資源、減少延遲。
優點:無需額外協議,利用 HTTP/2 特性。
缺點:不能直接用于動態數據推送,客戶端無法主動攔截。
五、WebRTC DataChannel(全雙工)
原理:基于 UDP 的點對點通信,適合瀏覽器間直接數據傳輸。
// 客戶端建立連接
const pc = new RTCPeerConnection();
const dataChannel = pc.createDataChannel('chat');dataChannel.onmessage = (e) => {console.log('收到消息:', e.data);
};
dataChannel.send('Hello Peer');// 需配合信令服務器交換 SDP 和 ICE 信息(代碼略)
適用場景:視頻會議、P2P 文件傳輸。
優點:低延遲、支持點對點通信。
缺點:需處理 NAT 穿透、需信令服務器。
六、WebTransport(實驗性,全雙工)
原理:基于 HTTP/3 的現代協議,支持雙向流和多路復用。
// 客戶端(需瀏覽器支持)
const transport = new WebTransport('https://server:port');
await transport.ready;
const stream = await transport.createBidirectionalStream();
const writer = stream.writable.getWriter();
writer.write(new TextEncoder().encode('Hello Server'));
const reader = stream.readable.getReader();
const { value } = await reader.read();
console.log('收到消息:', new TextDecoder().decode(value));
適用場景:未來替代 WebSocket 的高性能場景。
優點:基于 QUIC 協議,抗丟包能力強。
缺點:目前僅部分瀏覽器支持(如 Chrome 97+)。
對比總結
方案 | 協議 | 雙工類型 | 延遲 | 適用場景 |
---|---|---|---|---|
WebSocket | WS/WSS | 全雙工 | 低 | 實時聊天、高頻交互 |
SSE + HTTP | HTTP | 半雙工 | 中等 | 服務端主導的推送 |
長輪詢 | HTTP | 半雙工 | 高 | 兼容性要求高的低頻場景 |
HTTP/2 Push | HTTP/2 | 半雙工 | 低 | 資源預加載 |
WebRTC | UDP | 全雙工 | 極低 | P2P 通信、音視頻 |
WebTransport | HTTP/3 | 全雙工 | 極低 | 未來高性能應用 |
選擇建議:
- 需要 全雙工實時通信 ? WebSocket 或 WebTransport。
- 服務端單向推送為主 ? SSE。
- 兼容舊瀏覽器 ? 長輪詢。
- 點對點低延遲 ? WebRTC。