SignalR WebSocket终端报错排查:网站可通信但终端持续报错
报错信息
"WebSocket failed to connect. The connection could not be found on the server, either the endpoint may not be a SignalR endpoint, the connection ID is not present on the server, or there is a proxy blocking WebSockets. If you have multiple servers check that sticky sessions are enabled"
尽管网站控制台无警告、能正常连接服务器,且可通过connectionId接收其他客户端消息、在ASP.NET中正常完成授权,但运行程序时终端始终弹出上述报错。
相关代码
Angular 客户端代码
public connect(): void { this.hubConnection = new signalR.HubConnectionBuilder() .withUrl(this.webSockeUrl, { transport: signalR.HttpTransportType.WebSockets, skipNegotiation:true, accessTokenFactory: () => { return this.token!}, }) .withAutomaticReconnect() .build(); this.hubConnection .start() .then(() => console.log("Connection started")) .catch(err => console.error("Error establishing connection: ", err)); } public addReceiveMessageListener(): void { this.hubConnection.on("ReceiveMessage", (message: string) => { console.log("Receive Message from server:", message); }); this.hubConnection.on("ReceivePrivateMessage", (message: string) => { console.log("Receive Message from another client:", message); }); }
ASP.NET 服务器端代码
[Authorize] public class ChatHub : Hub { public async Task SendMessage(string connectionId, string message) { await Clients.Client(connectionId).SendAsync("ReceivePrivateMessage", message); } public override async Task OnConnectedAsync() { var connectionId = Context.ConnectionId; await Clients.All.SendAsync("ReceiveMessage", $"{connectionId} has joined"); } }
已尝试的解决方案
- 移除
skipNegotiation,但出现协商未完成问题 - 添加服务器端口44398至防火墙入站规则
- 开启Windows功能中的“WebSocket协议”
- 查阅多篇相关文章并尝试方案,但报错仍未消除
建议的排查方向
排查自动重连的触发原因
启用了withAutomaticReconnect(),终端的报错可能是重连过程中出现的临时失败。可以添加重连状态监听,确认报错是否来自重连阶段:this.hubConnection.onreconnecting(error => { console.error("Reconnecting failed: ", error); }); this.hubConnection.onreconnected(connectionId => { console.log("Reconnected with connectionId: ", connectionId); });确认WebSocket传输的配置兼容性
强制指定WebSockets传输并开启skipNegotiation,需要确保服务器端配置完全支持无协商的WebSocket连接。检查服务器Startup/Program.cs中是否正确配置了SignalR:app.MapHub<ChatHub>("/chathub"); // 确保路由与客户端的webSockeUrl一致同时,若服务器使用HTTPS,需确认客户端的
webSockeUrl是wss://开头而非ws://。检查服务器端的连接日志
在ASP.NET服务器端添加日志,查看连接断开的细节,确认是否有连接被意外断开后触发重连:public override async Task OnDisconnectedAsync(Exception? exception) { if (exception != null) { Console.WriteLine($"Connection {Context.ConnectionId} disconnected with error: {exception.Message}"); } else { Console.WriteLine($"Connection {Context.ConnectionId} disconnected normally"); } await base.OnDisconnectedAsync(exception); }排查代理或SSL中间件影响
即使防火墙规则已添加,若服务器部署在反向代理(如IIS、Nginx)之后,需确保代理已正确配置WebSocket支持:- IIS需确保WebSocket协议已启用,且站点的WebSocket设置未被禁用
- 若使用Nginx,需在配置中添加WebSocket的转发规则
验证连接ID的有效性
报错中提到“connection ID is not present on the server”,可以在客户端连接成功后,打印当前的connectionId,并在服务器端通过IHubContext<ChatHub>验证该ID是否存在于活跃连接列表中。
内容的提问来源于stack exchange,提问作者Long

