AspNetCore WebSocket无法发送Ping帧问题咨询
问题分析与解决方案
首先要明确:你遇到的问题并不是操作有误,而是ASP.NET Core 2.0版本的WebSocket中间件本身的限制——这个版本里的WebSocketOptions.KeepAliveInterval配置并不会自动让服务器发送Ping帧,这个自动发送Ping的功能是在ASP.NET Core 2.1及后续版本才被加入到官方中间件中的。
手动实现Ping帧发送(适配2.0版本)
既然你还在使用2.0版本,只能通过手动编写代码来定期发送Ping帧,具体步骤如下:
- 在WebSocket连接建立后,启动一个后台任务,按照你需要的间隔发送Ping帧。
- 使用
WebSocket.SendAsync方法,指定消息类型为WebSocketMessageType.Ping。 - 同时可以监听客户端的Pong响应,确保连接状态正常。
这里给你一个适配官方示例的代码片段:
app.Use(async (context, next) => { if (context.Request.Path == "/ws") { if (context.WebSockets.IsWebSocketRequest) { using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); var keepAliveToken = new CancellationTokenSource(); // 启动后台Ping任务 _ = Task.Run(async () => { while (webSocket.State == WebSocketState.Open) { try { var buffer = new ArraySegment<byte>(new byte[1]); await webSocket.SendAsync( buffer, WebSocketMessageType.Ping, endOfMessage: true, cancellationToken: keepAliveToken.Token); await Task.Delay(TimeSpan.FromSeconds(1), keepAliveToken.Token); } catch { // 处理发送异常,比如连接已断开 break; } } }); // 处理客户端消息的原有逻辑 var buffer = new byte[1024 * 4]; WebSocketReceiveResult result; do { result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); // 这里可以判断是否是Pong帧 if (result.MessageType == WebSocketMessageType.Pong) { // 记录Pong响应,确认客户端存活 Console.WriteLine("Received Pong from client"); } // 处理其他消息类型... } while (!result.CloseStatus.HasValue); // 取消Ping任务 keepAliveToken.Cancel(); await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); } else { context.Response.StatusCode = StatusCodes.Status400BadRequest; } } else { await next(); } });
长期解决方案:升级ASP.NET Core版本
如果条件允许,建议你升级到ASP.NET Core 2.1或更高版本——在这些版本中,WebSocketOptions.KeepAliveInterval配置会自动生效,中间件会定期向客户端发送Ping帧,无需手动编写额外代码。升级后你当前的配置代码就能正常工作。
另外需要注意:Chrome开发者工具在监控WebSocket帧时,Ping/Pong帧可能会被归类在"Frames"面板的"Other"类型下,你可以仔细检查这个分类下的帧数据,确认是否收到Ping帧。
内容的提问来源于stack exchange,提问作者JKJ
相关产品推荐
相关产品推荐

