发生WebSocketException后ClientWebSocket的正确重连方法
ClientWebSocket 连接丢失后的正确重连方案
异常原因说明
- 调用
ConnectAsync抛出InvalidOperationException:ClientWebSocket 是一次性使用的实例,只要该实例调用过一次ConnectAsync,无论连接成功、失败还是后续断开,状态都不可逆,无法再次发起连接,因此会提示已经启动。 - 调用
CloseAsync抛出WebSocketException:当服务器异常断开时,ClientWebSocket 状态会被标记为Aborted,而CloseAsync仅允许在Open、CloseReceived、CloseSent三个状态下执行,Aborted状态下不支持关闭操作。
正确重连步骤
- 旧连接触发断开/异常后,直接调用
Dispose()释放原有ClientWebSocket实例的资源,不需要尝试对原有实例执行关闭、重连操作 - 每次重连都创建全新的ClientWebSocket实例,不要复用历史实例
- 使用新实例调用
ConnectAsync发起新的连接请求即可
重连逻辑示例
private ClientWebSocket _wsClient; private readonly Uri _serviceUri = new Uri("ws://你的服务地址"); private CancellationTokenSource _connectCts; public async Task StartConnectAsync() { while (!_connectCts.IsCancellationRequested) { try { // 释放旧实例 _wsClient?.Dispose(); // 创建新实例 _wsClient = new ClientWebSocket(); // 发起连接 await _wsClient.ConnectAsync(_serviceUri, _connectCts.Token); // 连接成功后启动消息接收等业务逻辑 _ = ReceiveMessageLoopAsync(); break; } catch (WebSocketException) { // 连接失败,等待3秒后重试 await Task.Delay(3000, _connectCts.Token); } } } private async Task ReceiveMessageLoopAsync() { var buffer = new byte[1024 * 4]; try { while (_wsClient.State == WebSocketState.Open && !_connectCts.IsCancellationRequested) { var result = await _wsClient.ReceiveAsync(new ArraySegment<byte>(buffer), _connectCts.Token); // 处理收到的消息逻辑 } } catch (WebSocketException) { // 连接断开,触发重连 _ = StartConnectAsync(); } }
注意事项
- 仅当
ClientWebSocket.State为WebSocketState.Open时,才能正常执行收发消息操作 - 即便是客户端主动发起的优雅断开场景,也需要释放旧实例,重连时新建实例即可,不需要复用旧实例
内容的提问来源于stack exchange,提问作者amplifier
相关产品推荐
相关产品推荐

