C# WebSocket服务端向JS客户端发大消息触发错误1006求助
解决WebSocket大消息发送导致客户端1006异常断开的问题
我之前也踩过类似的坑——错误1006本质是客户端在解析服务端发送的WebSocket帧时遇到了格式错误,直接触发了无说明的异常关闭。结合你的情况,核心问题大概率是大消息没有按照WebSocket协议要求进行分片发送,下面给你一步步分析和解决:
为什么小消息正常,大消息会断开?
WebSocket协议没有强制规定单个帧的最大大小,但几乎所有客户端(包括浏览器原生WebSocket)对单帧大小都有默认限制(常见的是16KB或64KB)。如果服务端直接把67990字节的大消息打包成一个帧发送,客户端解析器会因为超出预期大小或帧格式不合法,直接断开连接,抛出不带额外说明的1006错误。
解决办法:手动实现大消息分片发送
WebSocket支持将一个大消息拆分成多个分片帧发送:
- 第一个帧设置
FIN位为false(表示后续还有帧),并指定消息类型(文本/二进制) - 中间所有帧同样
FIN位为false,消息类型设为连续帧(CONTINUATION) - 最后一个帧设置
FIN位为true,标志消息结束
在C#里,我们可以写一个扩展方法自动处理分片逻辑,不用手动拆分:
public static async Task SendLargeMessageAsync(this WebSocket webSocket, byte[] message, WebSocketMessageType messageType, CancellationToken cancellationToken) { // 按16KB分片,可根据实际需求调整,不要超过客户端支持的最大单帧大小 const int maxFrameSize = 16384; int currentOffset = 0; bool isFirstFrame = true; while (currentOffset < message.Length) { // 计算当前帧大小:取剩余数据和最大帧大小的较小值 int frameLength = Math.Min(maxFrameSize, message.Length - currentOffset); var frameBuffer = new ArraySegment<byte>(message, currentOffset, frameLength); // 发送帧:endOfMessage参数对应FIN位,只有最后一帧设为true await webSocket.SendAsync( frameBuffer, messageType, endOfMessage: currentOffset + frameLength == message.Length, cancellationToken); currentOffset += frameLength; isFirstFrame = false; } }
然后把原来直接发送大字节数组的代码,替换成调用这个扩展方法即可:
// 假设你的大消息字节数组是largeMessageBytes await webSocket.SendLargeMessageAsync(largeMessageBytes, WebSocketMessageType.Binary, cancellationToken); // 如果是文本消息,就用WebSocketMessageType.Text
额外检查点
- 确认消息类型匹配:如果发送的是二进制数据,一定要用
WebSocketMessageType.Binary,不要误用Text类型——大二进制数据按文本帧发送会直接导致解析失败。 - 服务端配置检查:如果你用的是ASP.NET Core WebSocket,确保没有手动限制过小的发送帧大小(默认无限制)。
- 客户端接收逻辑:虽然问题大概率出在服务端,但也可以确认客户端没有自行限制接收消息大小(浏览器原生WebSocket默认无限制)。
用这个分片方法发送大消息后,客户端就能正确拼接所有分片帧,不会再触发1006异常断开了。
内容的提问来源于stack exchange,提问作者Vladislav Vazhenin
相关产品推荐
相关产品推荐

