多WebSocket接收数据异常:超过3个时InternalClientWebSocket进入Aborted状态
我之前也碰到过类似的WebSocket并发连接问题,结合你给出的报错信息,咱们来一步步排查解决这个问题:
首先先明确你的问题场景:
当尝试从3个以上的WebSocket接收数据时出现异常,仅使用1个、2个或3个WebSocket时运行完全正常。异常发生在代码行:
tasks.Add(Send(webSocket, "11"));
异常信息如下:
Exception: System.Net.WebSockets.WebSocketException (0x80004005): The 'System.Net.WebSockets.InternalClientWebSocket' instance cannot be used for communication because it has been transitioned into the 'Aborted' state. ---> System.OperationCanceledException: The ...
可能的原因及对应解决方法
1. 复用了WebSocket实例(最常见原因)
如果你的代码里不小心在多个任务中共享了同一个WebSocket实例,或者没有为每个连接创建独立的实例,就会触发这种状态异常——毕竟每个WebSocket连接都有自己的状态生命周期,多任务操作同一个实例必然会导致状态冲突。
解决步骤:
确保每个并发任务对应一个独立的ClientWebSocket实例,不要复用:
// 正确示例:为每个连接单独创建实例并初始化 foreach (var targetUrl in yourTargetUrls) { var webSocket = new ClientWebSocket(); // 先确保连接成功再加入任务列表 await webSocket.ConnectAsync(new Uri(targetUrl), CancellationToken.None); if (webSocket.State == WebSocketState.Open) { tasks.Add(Send(webSocket, "11")); } }
2. 取消令牌(CancellationToken)被提前触发
报错里的OperationCanceledException是个关键线索——如果你所有WebSocket连接都共用了同一个CancellationTokenSource,并且在某个时刻提前调用了Cancel(),就会导致所有关联的WebSocket连接被强制中止,进入Aborted状态。
解决步骤:
- 为每个WebSocket连接使用独立的取消令牌,或者确保主令牌不会在所有连接完成前被触发;
- 如果需要批量管理,可以创建多个
CancellationTokenSource,或者用LinkedTokenSource来单独控制每个连接的取消逻辑。
3. Send方法里有同步阻塞操作
如果你的Send方法内部用了.Wait()、.Result这类同步阻塞调用,当并发数超过3个时,线程池资源会被迅速耗尽,导致后续的WebSocket连接无法维持正常状态,最终被标记为Aborted。
解决步骤:
把Send方法改成完全异步的,避免任何同步阻塞:
private async Task Send(ClientWebSocket webSocket, string message) { try { var sendBuffer = Encoding.UTF8.GetBytes(message); await webSocket.SendAsync( new ArraySegment<byte>(sendBuffer), WebSocketMessageType.Text, endOfMessage: true, CancellationToken.None ); // 接收响应也要用异步 var receiveBuffer = new byte[1024]; var receiveResult = await webSocket.ReceiveAsync( new ArraySegment<byte>(receiveBuffer), CancellationToken.None ); // 处理接收到的数据... // 最后别忘了正常关闭连接 await webSocket.CloseAsync( WebSocketCloseStatus.NormalClosure, "Connection completed", CancellationToken.None ); } catch (WebSocketException ex) { // 这里可以添加日志,记录具体的异常信息 Console.WriteLine($"WebSocket error: {ex.Message}, State: {webSocket.State}"); } }
4. 系统或框架的并发连接限制
有些系统环境(比如Windows默认的TCP连接限制)或者旧版本的.NET框架,可能对并发WebSocket连接数有默认限制。
解决步骤:
如果是通过HttpClient创建WebSocket连接的,可以调整MaxConnectionsPerServer参数:
var handler = new HttpClientHandler { MaxConnectionsPerServer = 100 // 根据你的需求调整这个数值 }; var httpClient = new HttpClient(handler); // 后续通过httpClient创建WebSocket连接
额外调试小技巧
- 在把WebSocket实例加入任务前,先检查
webSocket.State是否为Open,避免把已异常的实例加入任务; - 捕获异常时,输出完整的堆栈信息和WebSocket当前状态,能帮你更快定位问题;
- 加个日志工具,记录每个WebSocket的连接、发送、接收、关闭节点,方便追踪异常发生的时机。
内容的提问来源于stack exchange,提问作者Adam Miklosi

