You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core 2 MVC中异常发生时关闭WebSocket并传递异常信息给客户端

在ASP.NET Core 2 MVC中处理WebSocket异常并通知客户端

我之前在做ASP.NET Core的WebSocket项目时也遇到过类似需求,下面是经过验证的实现方案,核心是通过try-catch包裹所有WebSocket相关逻辑,在异常发生时先向客户端发送错误信息,再优雅关闭连接。

步骤1:修改Startup.cs中的WebSocket中间件

首先在Configure方法的WebSocket中间件里添加异常捕获逻辑,确保连接建立和后续处理过程中的异常都能被处理:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // 保留你原有的其他中间件配置(比如UseStaticFiles、UseMvc等)

    app.Use(async (context, next) =>
    {
        if (context.WebSockets.IsWebSocketRequest)
        {
            if (context.Request.Path == "/ws")
            {
                WebSocket webSocket = null;
                try
                {
                    // 接受WebSocket连接
                    webSocket = await context.WebSockets.AcceptWebSocketAsync();
                    // 实例化自定义处理类
                    var webSocketHandler = new WebSocketConnectionHandler(webSocket);
                    // 启动连接处理逻辑
                    await webSocketHandler.HandleConnectionAsync();
                }
                catch (Exception ex)
                {
                    // 异常处理:发送错误信息并关闭连接
                    if (webSocket != null && webSocket.State == WebSocketState.Open)
                    {
                        // 向客户端发送错误文本
                        var errorBytes = Encoding.UTF8.GetBytes($"服务器异常:{ex.Message}");
                        await webSocket.SendAsync(
                            new ArraySegment<byte>(errorBytes),
                            WebSocketMessageType.Text,
                            endOfMessage: true,
                            cancellationToken: CancellationToken.None);

                        // 以错误状态码关闭连接,附带异常描述
                        await webSocket.CloseAsync(
                            WebSocketCloseStatus.InternalServerError,
                            $"错误详情:{ex.Message}",
                            CancellationToken.None);
                    }
                }
                finally
                {
                    // 确保WebSocket资源被释放
                    webSocket?.Dispose();
                }
                // 跳过后续中间件,因为WebSocket是长连接
                return;
            }
        }
        // 非WebSocket请求,继续执行后续中间件
        await next();
    });

    // 其他中间件配置...
}

步骤2:在自定义处理类中添加异常捕获

你的自定义WebSocket处理类(比如WebSocketConnectionHandler)里的消息收发逻辑也需要包裹try-catch,避免单个消息处理异常导致整个连接意外断开:

public class WebSocketConnectionHandler
{
    private readonly WebSocket _webSocket;
    private readonly byte[] _buffer = new byte[1024 * 4]; // 4KB接收缓冲区

    public WebSocketConnectionHandler(WebSocket webSocket)
    {
        _webSocket = webSocket;
    }

    public async Task HandleConnectionAsync()
    {
        try
        {
            while (_webSocket.State == WebSocketState.Open)
            {
                // 接收客户端消息
                var receiveResult = await _webSocket.ReceiveAsync(
                    new ArraySegment<byte>(_buffer),
                    CancellationToken.None);

                // 处理客户端消息的逻辑(这里替换成你的业务代码)
                var receivedMessage = Encoding.UTF8.GetString(_buffer, 0, receiveResult.Count);
                await ProcessReceivedMessageAsync(receivedMessage);

                // 如果客户端主动关闭连接,退出循环
                if (receiveResult.CloseStatus.HasValue)
                {
                    await _webSocket.CloseAsync(
                        receiveResult.CloseStatus.Value,
                        receiveResult.CloseStatusDescription,
                        CancellationToken.None);
                }
            }
        }
        catch (Exception ex)
        {
            // 处理消息过程中的异常
            if (_webSocket.State == WebSocketState.Open)
            {
                var errorBytes = Encoding.UTF8.GetBytes($"消息处理失败:{ex.Message}");
                await _webSocket.SendAsync(
                    new ArraySegment<byte>(errorBytes),
                    WebSocketMessageType.Text,
                    true,
                    CancellationToken.None);

                // 根据异常类型选择合适的关闭状态码,比如InvalidPayloadData表示消息格式错误
                await _webSocket.CloseAsync(
                    WebSocketCloseStatus.InvalidPayloadData,
                    ex.Message,
                    CancellationToken.None);
            }
        }
    }

    // 示例:业务消息处理方法
    private async Task ProcessReceivedMessageAsync(string message)
    {
        // 这里写你的业务逻辑,比如解析消息、操作数据库等
        // 如果业务逻辑抛出异常,会被上层的try-catch捕获
        if (string.IsNullOrEmpty(message))
        {
            throw new ArgumentException("空消息不允许处理");
        }
        // 其他处理逻辑...
    }
}

关键注意事项

  • 选择合适的关闭状态码:根据异常类型对应WebSocketCloseStatus枚举值,比如:
    • InternalServerError:服务器内部错误(比如数据库连接失败)
    • InvalidPayloadData:客户端发送的消息格式错误
    • PolicyViolation:违反业务规则(比如未授权操作)
  • 确保连接状态有效:发送错误信息和关闭连接前,一定要检查WebSocket.State是否为Open,避免触发新的异常
  • 资源释放:通过finally块确保WebSocket被正确释放,防止资源泄漏
  • 跳过后续中间件:处理完WebSocket请求后要return,不要调用next(),因为WebSocket是长连接,后续中间件不需要介入

内容的提问来源于stack exchange,提问作者Simon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:26:38