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

ASP.NET Core WebSocket如何检测客户端网络连接中断?

如何在ASP.NET Core WebSockets中快速检测客户端网络断开

针对你遇到的服务器要20分钟才感知客户端断连的问题,这里有几个实用的解决办法:

一、实现应用层自定义心跳机制

既然ManagedWebSocket内置的Ping/Pong没法直接追踪,那就自己在业务层加心跳:

  • 客户端每隔固定时间(比如10秒)发送一条自定义心跳消息(比如{"cmd":"heartbeat"})
  • 服务器端维护一个字典,记录每个WebSocket连接的最后活跃时间
  • 启动一个后台定时任务(比如用IHostedService),每隔一段时间遍历字典,把超过超时阈值(比如30秒)的连接主动关闭

示例代码片段:

// 服务器端维护连接状态
private static readonly ConcurrentDictionary<WebSocket, DateTime> _activeConnections = new();

// 接收消息时更新活跃时间
async Task HandleWebSocketConnection(WebSocket webSocket)
{
    _activeConnections.TryAdd(webSocket, DateTime.UtcNow);
    var buffer = new byte[1024 * 4];

    try
    {
        while (webSocket.State == WebSocketState.Open)
        {
            var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            // 更新活跃时间
            _activeConnections[webSocket] = DateTime.UtcNow;

            if (result.MessageType == WebSocketMessageType.Text)
            {
                var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
                // 处理心跳消息(可选,也可以只更新时间不处理)
                if (message.Contains("heartbeat"))
                {
                    await webSocket.SendAsync(Encoding.UTF8.GetBytes("pong"), WebSocketMessageType.Text, true, CancellationToken.None);
                }
            }
        }
    }
    catch (WebSocketException)
    {
        // 连接异常断开,清理
        _activeConnections.TryRemove(webSocket, out _);
    }
}

// 后台清理任务
public class ConnectionCleanupService : IHostedService, IDisposable
{
    private Timer _timer;

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _timer = new Timer(CheckInactiveConnections, null, TimeSpan.Zero, TimeSpan.FromSeconds(15));
        return Task.CompletedTask;
    }

    private void CheckInactiveConnections(object state)
    {
        var now = DateTime.UtcNow;
        var inactiveConnections = _activeConnections.Where(kv => now - kv.Value > TimeSpan.FromSeconds(30)).Select(kv => kv.Key).ToList();

        foreach (var conn in inactiveConnections)
        {
            if (conn.State == WebSocketState.Open)
            {
                conn.CloseAsync(WebSocketCloseStatus.NormalClosure, "Inactive connection", CancellationToken.None).Wait();
            }
            _activeConnections.TryRemove(conn, out _);
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _timer?.Change(Timeout.Infinite, 0);
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

二、配置TCP层面的KeepAlive

WebSocket基于TCP协议,可以通过配置Kestrel的TCP KeepAlive参数来缩短断连检测时间:
在Program.cs中添加Kestrel配置:

builder.WebHost.ConfigureKestrel(options =>
{
    options.ListenAnyIP(5000, listenOptions =>
    {
        listenOptions.UseConnectionLogging();
        listenOptions.TcpKeepAlive.Time = TimeSpan.FromSeconds(10);
        listenOptions.TcpKeepAlive.IdleTime = TimeSpan.FromSeconds(10);
        listenOptions.TcpKeepAlive.Interval = TimeSpan.FromSeconds(5);
    });
});

这样TCP层会主动发送KeepAlive包,一旦客户端断连,服务器能更快收到TCP层面的断开通知。

三、优化接收循环的异常处理

即使不用心跳,在服务器的消息接收循环里,一旦连接异常断开,ReceiveAsync会抛出WebSocketException或者返回带有CloseStatus的结果,你可以在循环里捕获这些情况,及时清理连接:

async Task HandleWebSocketConnection(WebSocket webSocket)
{
    var buffer = new byte[1024 * 4];
    try
    {
        while (webSocket.State == WebSocketState.Open)
        {
            var result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);

            if (result.MessageType == WebSocketMessageType.Close)
            {
                await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
                break;
            }

            // 处理业务消息
        }
    }
    catch (WebSocketException ex)
    {
        // 连接异常断开,这里可以做日志记录、清理连接等操作
        Console.WriteLine($"Connection closed unexpectedly: {ex.Message}");
    }
    finally
    {
        webSocket.Dispose();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:13:25