websocket发送arraybuffer前必须设置ws.binarytype = 'arraybuffer',否则服务端可能收到blob或转码数据;应于onopen中设置,用typedarray包装更安全,接收时需用dataview或typedarray解析。

WebSocket发送ArrayBuffer前必须设置binaryType
WebSocket实例默认把二进制数据当Blob处理,直接 send(arrayBuffer) 虽然不报错,但服务端收到的可能是Blob或被转码过的字符串。必须在连接建立后、发送前显式设置:ws.binaryType = 'arraybuffer'。这个设置只影响后续接收的数据类型,对已发送的数据无效——所以它得放在 onopen 回调里,不能漏。
常见错误是发完才发现服务端解析失败,抓包看到 payload 是乱码或长度异常,大概率就是 binaryType 没设对。Chrome DevTools 的 Network 面板里 WebSocket 帧详情里能看到实际传输的 type,可用来验证。
用TypedArray包装ArrayBuffer再send更安全
直接 ws.send(arrayBuffer) 可以工作,但多数场景你操作的是具体数值(比如 float32 坐标、int16 音频采样),裸 ArrayBuffer 没有类型信息,容易出错。推荐先用 TypedArray 包装:
const buffer = new ArrayBuffer(8); const view = new Float32Array(buffer); view[0] = 1.5; view[1] = -2.3; ws.send(buffer); // 发送底层 buffer 即可
注意:TypedArray 的 .buffer 属性才是真实内存块,ws.send(view) 会触发隐式转换,行为不可控;务必传 view.buffer 或原始 ArrayBuffer。
另外,如果 ArrayBuffer 来自 fetch().arrayBuffer() 或 FileReader.readAsArrayBuffer(),它本身已是完整块,无需再包装,直接 send 即可。
服务端收到的ArrayBuffer需用DataView或TypedArray解析
前端收到的 message 事件中,event.data 是 ArrayBuffer(前提是客户端设置了 binaryType = 'arraybuffer')。不能直接 JSON.parse(event.data),也不能用 TextDecoder 盲解——除非你确定它是 UTF-8 字符串。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
典型解析方式:
- 若协议约定前4字节是 int32 消息类型:
new DataView(event.data).getInt32(0) - 若整块是 float32 数组:
new Float32Array(event.data) - 若结构混合(如 header + payload):
const dv = new DataView(event.data); const len = dv.getUint32(0); const payload = event.data.slice(4, 4 + len)
切记:TypedArray 构造函数接受 ArrayBuffer,但不会拷贝内存;slice() 返回新 ArrayBuffer,而 subarray() 返回共享内存的视图——根据是否需要隔离做选择。
大 ArrayBuffer分片发送时需自行处理粘包与边界
WebSocket 协议本身不保证消息边界,尤其当连续快速 send 多个 ArrayBuffer 时,服务端可能合并接收(TCP 层行为)。浏览器端不会自动拆分或加帧头,一切靠应用层约定。
简单方案:每个 ArrayBuffer 前加 4 字节 uint32 表示长度(小端),服务端按长度读取;复杂协议建议用 Protocol Buffers 或 MessagePack 序列化后再 send。
另一个坑:Chrome 对单次 send() 的 ArrayBuffer 大小无硬限制,但过大会触发主线程阻塞(尤其 >1MB)。如需传大文件,务必用 setTimeout 或 queueMicrotask 分批,每批控制在 64KB 内,并监听 ws.bufferedAmount 防止压爆内存。
最后提醒:ArrayBuffer 一旦被 send,浏览器可能立即复用其内存,不要在 send 后继续修改它——如有需要,先 structuredClone() 或手动复制。










