1. WebSocket
-
核心:基于TCP的全双工通信协议,通过一个持久连接实现客户端与服务器的双向实时数据交换。
-
优点:
真正的双向实时通信:客户端和服务器可以随时主动发送数据。
低延迟:建立连接后,数据传输无需HTTP握手开销,延迟极低。
高效:数据以帧形式传输,头部开销远小于HTTP。
标准协议:现代浏览器原生支持,是HTML5标准的一部分。
-
缺点:
兼容性与连接管理:需自行处理连接建立、维护、断开重连和心跳保活,代码相对复杂。
服务器资源消耗:每个活跃连接都需要服务器维持一个TCP连接,高并发时对服务器资源是挑战。
协议升级:需要服务器和客户端都专门支持WebSocket协议。
-
使用场景:
在线聊天室、即时通讯
多人在线协作编辑(如文档、表格)
实时游戏、股票行情、金融交易仪表盘
需要高频率、低延迟双向数据交换的任何应用
代码示例(原生):
// 客户端
const socket = new WebSocket('wss://your-server.com/ws');
// 连接打开
socket.addEventListener('open', (event) => {
socket.send('Hello Server!');
});
// 接收消息
socket.addEventListener('message', (event) => {
console.log('Message from server:', event.data);
});
// 处理错误和关闭
socket.addEventListener('error', (event) => { /* ... */ });
socket.addEventListener('close', (event) => { /* ... */ });
2. Server-Sent Events(SSE)
-
核心:基于HTTP的单向通信,允许服务器主动向客户端推送数据流。
-
优点:
简单易用:基于HTTP,无需额外协议,服务器端实现简单。
自动重连:浏览器原生支持在连接断开后自动重连。
良好的HTTP兼容性:可以利用HTTP/2的多路复用、头部压缩等特性。
轻量级:专门为服务器到客户端的文本流设计。
-
缺点:
单向通信:只能从服务器向客户端推送数据,客户端无法通过此通道向服务器发送数据(仍需使用XHR/Fetch)。
文本协议:默认只支持UTF-8文本传输,传输二进制数据需额外编码(如Base64)。
连接数限制:在HTTP/1.1下,浏览器对同一域名的并发连接数有限制(通常6个)。
-
使用场景:
实时新闻推送、微博更新
股票价格实时变动
服务器日志流监控、任务进度更新
任何以服务器向客户端单向通知为主的场景
代码示例
// 客户端
const eventSource = new EventSource('/api/stream');
// 监听通用消息
eventSource.onmessage = (event) => {
console.log('New event:', event.data);
};
// 监听自定义事件类型
eventSource.addEventListener('stock-update', (event) => {
const data = JSON.parse(event.data);
updateStockPrice(data);
});
// 处理错误(浏览器会自动重连)
eventSource.onerror = (event) => {
console.error('EventSource failed.');
};
3. WebRTC
-
核心:一组支持浏览器间进行点对点实时音视频和数据传输的API。
-
优点:
点对点直接通信:数据直接在浏览器间传输,延迟极低,减轻了服务器中转压力。
强大的媒体处理能力:原生支持音视频捕获、编码、传输,适合高质量媒体流。
数据通道灵活:除了音视频,也提供通用的RTCDataChannel,可用于传输任意数据。
-
缺点:
实现复杂度高:需要处理信令交换、NAT穿透(STUN/TURN)、连接建立和维护,逻辑复杂。
依赖信令服务器:建立P2P连接前,仍需通过WebSocket等服务器交换元数据(信令)。
网络环境要求:复杂的网络环境(如对称NAT)下可能无法直接连通,需要TURN服务器中转,产生额外成本。
-
使用场景:
视频会议、在线课堂、直播连麦
浏览器间的P2P文件共享
远程桌面控制、云游戏
需要超低延迟数据交换的协作应用
代码示例(建立数据通道):
// 简化的信令部分略过,假设通过WebSocket交换了 `offer`, `answer`, `candidate`
// 本地Peer
const localPeer = new RTCPeerConnection();
const dataChannel = localPeer.createDataChannel('chat');
dataChannel.onopen = () => {
dataChannel.send('Hello via P2P!');
};
dataChannel.onmessage = (event) => {
console.log('Received:', event.data);
};
// 远程Peer
const remotePeer = new RTCPeerConnection();
remotePeer.ondatachannel = (event) => {
const channel = event.channel;
channel.onmessage = (event) => {
console.log('P2P message:', event.data);
};
};
4. MQTT over WebSocket
-
核心:基于发布/订阅模式的轻量级消息协议,通常通过WebSocket连接在浏览器中使用。
-
优点:
极低的协议开销:报文头非常小,节省带宽,特别适合网络环境差的场景。
灵活的发布/订阅模型:客户端可以订阅感兴趣的主题,实现消息的精确分发。
完善的消息服务质量:提供至少一次、至多一次、恰好一次三种传递保证。
适合不稳定网络:支持遗嘱消息、持久会话,应对网络波动能力强。
-
缺点:
需要代理服务器:必须部署和运维MQTT代理(如Mosquitto, EMQ X)。
额外学习成本:需要理解其协议模型(主题、QoS等)。
并非浏览器原生:需通过WebSocket隧道传输,并使用客户端库(如Paho, MQTT.js)。
-
使用场景:
物联网设备监控与控制
移动端即时通讯(如微信小程序)
需要跨多端、多客户端状态同步的场景
网络带宽受限或设备资源有限的环境
代码示例(使用MQTT.js库):
// 客户端
import mqtt from 'mqtt';
const client = mqtt.connect('wss://mqtt-broker.example.com:8884');
client.on('connect', () => {
// 订阅主题
client.subscribe('room/+/temperature');
// 发布消息
client.publish('room/101/temperature', '22.5');
});
client.on('message', (topic, message) => {
console.log(`Received on ${topic}: ${message.toString()}`);
});
5. 长轮询
-
核心:客户端发起一个请求,服务器持有该请求直到有数据可送或超时,然后客户端立即发起下一个请求。
-
优点:
兼容性极佳:使用最基础的HTTP,几乎所有浏览器和环境都支持。
实现简单:服务器端逻辑相对直接,无需维持持久连接。
穿透性好:能通过大多数防火墙和代理。
-
缺点:
高延迟:服务器有数据时不能立即推送,必须等待客户端下一次请求。
资源浪费:频繁的HTTP请求和响应(即使没有数据)带来不必要的头部开销和连接成本。
服务器压力:大量的并发挂起请求可能消耗服务器资源(如线程、文件描述符)。
-
使用场景:
兼容性要求极高的老旧系统
作为不支持WebSocket或SSE的环境下的降级方案
推送频率不高的简单通知场景
代码示例:
function longPoll() {
fetch('/api/long-poll')
.then(response => response.json())
.then(data => {
console.log('New data:', data);
// 处理完数据后立即发起下一次请求
longPoll();
})
.catch(error => {
console.error('Polling error, retry...', error);
setTimeout(longPoll, 3000); // 出错后延时重试
});
}
// 启动长轮询
longPoll();
建议与总结
选择建议:
-
默认首选 WebSocket:当你的应用需要真正的、低延迟的双向通信(如聊天、实时游戏、协作工具)时,应毫不犹豫地选择WebSocket。对于生产环境,强烈建议使用 Socket.IO 或 SockJS 这类库,它们封装了重连、心跳、降级等复杂逻辑。
-
优先考虑 Server-Sent Events:如果你的场景是纯粹的服务器向客户端推送通知或数据流(如新闻、股价、监控),SSE是比WebSocket更简单、更高效的选择。
-
点对点传输用 WebRTC:当应用核心是浏览器之间的音视频通话或直接数据传输时,WebRTC是唯一的标准答案。记住,它依然需要WebSocket或类似技术作为信令通道。
-
特定场景选择 MQTT:在物联网、移动应用或网络环境不稳定、带宽敏感的场景下,MQTT的轻量级和发布/订阅模型会带来巨大优势。
-
将长轮询作为降级方案:在现代Web开发中,长轮询不应作为首选,而应作为在不支持WebSocket和SSE的极端老旧环境下的兼容性降级备选。
总结:
现代前端实时通信技术已形成清晰的分工:WebSocket是双向实时交互的基石,SSE是服务器推送的利器,WebRTC攻克了点对点媒体与数据传输,MQTT则在物联网等特定领域展现其轻量优势。技术选型的关键在于深刻理解业务场景的核心需求(是双向还是单向?延迟要求多高?数据形式是什么?),并结合团队技术栈和运维成本做出权衡。对于大多数新项目,从WebSocket(及其封装库)或SSE开始评估,通常不会出错。