跳转到主内容
极星编程网:以代码为星,赴技术山海!

网页中如何定义双向通信_WebSocket协议实现实时数据交互

WebSocket是唯一原生支持真正双向通信的浏览器方案,因其基于TCP长连接、握手后复用同一连接并免HTTP头开销;fetch和XMLHttpRequest本质为单向请求-响应模型,轮询会导致延迟高、开销大、连接频繁重建。
WebSocket
是浏览器中实现真正双向通信的唯一原生方案,不需要轮询、不依赖 HTTP 请求-响应模型,连接建立后客户端和服务器可随时互发消息。 为什么不能用
fetch
或
XMLHttpRequest
做双向通信 它们本质是单向请求工具:客户端发一次,服务端回一次,之后连接就断了。即使加
setInterval
轮询,也会带来明显延迟、重复 header 开销、连接频繁重建等问题。而
WebSocket
握手成功后复用同一个 TCP 连接,后续所有数据帧都不带 HTTP 头,协议开销极小。 常见错误现象包括: 用户看到“新消息”总比实际晚 2–5 秒(轮询间隔导致) 服务端日志里每秒出现数百个
GET /api/notify
请求(其实是假实时) 移动端耗电快、流量消耗异常高(高频短连接)
WebSocket
连接必须用
wss://
吗 不是必须,但生产环境几乎必须。HTTP 页面加载时,浏览器会阻止非加密的
ws://
升级请求(Mixed Content 报错),控制台直接报
Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS
。 所以实际部署要注意: 前端页面走
https://
→ 后端 WebSocket 地址必须用
wss://
本地开发用
http://localhost
时,
ws://
可以临时工作,但别依赖它 Nginx 反向代理
wss://
需显式配置
Upgrade
和
Connection
头,漏掉就会卡在
readyState === 0
如何判断连接是否真正可用,而不是“假在线”
readyState
值为
1
(
OPEN
)只代表握手完成,不代表网络通或服务端逻辑就绪。真实场景中常遇到: WebSocket 8.18.2 WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。 下载 连接已打开,但服务端没做鉴权,直接关闭(
onclose
触发,
event.code
是
4001
类自定义码) 防火墙或代理中途静默断连,客户端仍显示
readyState === 1
服务端进程崩溃,但 TCP 连接未及时 FIN,客户端无感知 因此必须加心跳:
let heartbeatTimer; socket.onopen = () => { heartbeatTimer = setInterval(() => { if (socket.readyState === WebSocket.OPEN) { socket.send(JSON.stringify({ type: 'ping' })); } }, 30000); }; socket.onmessage = (e) => { const data = JSON.parse(e.data); if (data.type === 'pong') return; // 忽略心跳响应 // 处理业务消息 }; socket.onclose = () => { clearInterval(heartbeatTimer); };
服务端广播时为什么有些客户端收不到消息 最常见原因是没检查
client.readyState === WebSocket.OPEN
。Node.js 的
ws
库中,
client.send()
对已断开但尚未触发
close
事件的连接会静默失败,不抛错也不重试。 正确写法必须逐个判断状态:
wss.clients.forEach(client => { if (client.readyState === WebSocket.OPEN) { client.send(payload); } else { console.warn('Dropped message: client not ready', client.readyState); } });
另外注意:
ws
默认不支持跨域,若前端域名与服务端不一致,需手动设置
verifyClient
或启用
options.origin
白名单,否则连接直接被拒绝,前端看不到任何错误,只有
onerror
被触发一次。 真实双向通信的关键不在“连上”,而在“持续可控地交换”。很多项目卡在连接能建、消息发不出、断连不重连、广播漏人这些细节上,而不是协议本身有多难。

相关文章