WebSocket无单条消息尺寸硬性限制,实际受限于浏览器、服务端、网络及内存;浏览器可能自动分片(阈值不统一),Node.js ws库默认激进分片,Java-WebSocket需手动启用;原生API不支持手动分片,仅部分底层库提供;大消息易引发内存暴增、超时或静默丢帧,推荐业务层主动分块传输。

WebSocket本身没有硬性规定单条消息的最大尺寸,但实际能发多大,取决于浏览器、服务端实现、网络环境和内存限制——不是“能不能”,而是“发了之后对方能不能收全、收得稳”。
浏览器自动分片的触发阈值不统一
Chrome、Firefox、Edge 在 ws.send() 传入超大 ArrayBuffer(比如 >16MB)时,可能自动拆成多个帧,但这个阈值没有标准定义:有的版本在 4MB 就分,有的到 64MB 才动。你无法通过 JS 控制或感知是否已分片,onmessage 仍只触发一次,内容完整。
- DevTools 的 Network → WebSocket → Frames 面板可确认是否真被分了(看 FIN 和 Opcode 序列)
- 若服务端用的是 Node.js 的
ws库,默认fragmentOutgoingMessages: true且fragmentationThreshold: 16384(16KB),远比浏览器激进 - Java-WebSocket 默认不自动分片,超大消息直接 OOM,必须显式启用
ContinuousFrame或设setMaxBinaryMessageBufferSize
手动分片只在特定库中可用
原生浏览器 WebSocket API 不提供 sendFirstFragment、sendFragment 这类接口,所谓“手动分片”仅存在于 uWebSockets.js、SocketRocket(iOS)、ws(Node.js)等底层可控的实现中。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
-
uWS.ws.sendFirstFragment()+sendFragment()+sendLastFragment()是完整链路,必须按序调用,中间不能穿插其他 send - SocketRocket 需自行切块 +
sendData:,并带元数据(如chunkIndex、totalChunks)走文本帧协商 - Java-WebSocket 的
Partial接口(onMessage(byte[], boolean last))是接收端分片回调,发送端仍需自己分好再 send
真正卡住你的往往不是协议,而是内存和超时
即使协议允许发 100MB,ws.send(new ArrayBuffer(100 * 1024 * 1024)) 在 Chrome 里可能卡死 UI,在 Node.js 里可能让 V8 GC 崩溃,服务端也可能因未设 maxPayload 直接断连。
- 浏览器发送前会尝试复制整个 buffer 到网络栈,内存峰值 = 原始数据大小 × 2~3 倍
- 服务端如 nginx 做反向代理,默认
client_max_body_size和 WebSocketproxy_buffering都可能截断大帧 - 移动端 WebView(尤其旧版)对单帧 >2MB 更敏感,容易静默丢帧
别把分片当万能解药。最稳妥的做法,是业务层主动切块(比如每 64KB 一个 send()),附带序号和校验和,由应用逻辑重组——这样既绕开所有底层差异,又便于重传、进度反馈和内存控制。

















