SignalR Core连接因错误码1007异常断开,求排查解决
解决SignalR WebSocket错误1007(非UTF-8编码)的问题
我之前排查过几乎一模一样的问题,这个1007错误看起来是UTF-8编码问题,但根源其实是大字符串传输时的帧处理异常,尤其是包含大量多字节特殊字符(比如æøå,每个占2个UTF-8字节)的场景。咱们一步步拆解:
为什么你的强制编码没用?
先把那个forceUnicodeEncoding函数删掉——它反而会搞乱编码。JavaScript字符串本身就是UTF-16编码,SignalR会自动帮你转成标准UTF-8再发送。而unescape(encodeURIComponent(string))这套操作是过时的URI编码转义,会把UTF-8字节转成Latin-1字符,反而生成不符合规范的字符串,加重问题。
核心问题:大字符串的帧拆分截断
当你发送超长字符串时,WebSocket会把数据拆分成多个帧传输。如果某个多字节的UTF-8字符刚好被拆在两个帧的边界上,服务端解析时就会认为这是无效的UTF-8序列,直接触发1007错误关闭连接。少量特殊字符不会触发,是因为数据量小,不会被拆帧。
具体解决方案
1. 调整SignalR的消息大小限制(最直接)
默认情况下,SignalR的最大接收消息大小是32KB左右,当你的字符串超过这个阈值时,就容易出现帧拆分问题。在服务端和客户端都调整配置:
服务端(Program.cs/Startup.cs):
builder.Services.AddSignalR(options => { // 根据你的需求设置更大的阈值,比如1MB options.MaximumReceiveMessageSize = 1024 * 1024; // 开启详细错误,方便后续排查 options.EnableDetailedErrors = true; });
客户端:
const hubConnection = new signalR.HubConnectionBuilder() .withUrl("/yourHubEndpoint") .configureLogging(signalR.LogLevel.Information) .withAutomaticReconnect() // 加上自动重连,提升体验 .build(); // 可以适当调整超时和心跳参数 hubConnection.serverTimeoutInMilliseconds = 30000; hubConnection.keepAliveIntervalInMilliseconds = 15000;
2. 分块发送大内容(适合超大型文本)
如果你的文本内容经常超过1MB,可以把内容拆成小块发送,避免单帧过大:
客户端代码:
// 分块发送函数,chunkSize可根据需求调整 function sendContentInChunks(content, chunkSize = 1000) { for (let i = 0; i < content.length; i += chunkSize) { const chunk = content.slice(i, i + chunkSize); // 告诉服务端这是第一块、最后一块还是中间块 hubConnection.invoke('SendContentChunk', chunk, i === 0, i + chunkSize >= content.length); } } // 替换原来的调用: // this.hubConnection.invoke('SendContent', contentString); sendContentInChunks(contentString);
Hub代码:
private static string _contentString = string.Empty; public async Task SendContentChunk(string chunk, bool isFirst, bool isLast) { // 第一块重置缓存,后续块拼接 if (isFirst) _contentString = chunk; else _contentString += chunk; // 最后一块发送给其他用户 if (isLast) { await Clients.Others.SendAsync("ReceiveContent", _contentString); } }
3. 用二进制格式传输(最稳妥的编码保障)
直接把字符串转成UTF-8二进制数据发送,完全避免编码转换的歧义:
客户端代码:
// 字符串转UTF-8 ArrayBuffer function stringToUtf8Buffer(str) { const encoder = new TextEncoder(); return encoder.encode(str); } // 调用时传二进制数据 this.hubConnection.invoke('SendContentBinary', stringToUtf8Buffer(contentString));
Hub代码:
public async Task SendContentBinary(byte[] textBytes) { _contentString = Encoding.UTF8.GetString(textBytes); await Clients.Others.SendAsync("ReceiveContent", _contentString); }
验证步骤
- 删除你自己写的
forceUnicodeEncoding函数; - 先尝试调整消息大小限制,测试大量特殊字符的场景;
- 如果还出现问题,再试试分块或二进制传输的方案。
内容的提问来源于stack exchange,提问作者Simon Christiansen
相关产品推荐
相关产品推荐

