☰
ASP.NET Core 中的 WebSockets 实战:中间件、握手与全双工实时通信
2026/10/6 2:40:59 网站建设 项目流程
  • 文档
  • 教程
  • 知识库

【免费下载链接】developer-roadmap

Interactive roadmaps, guides and other educational content to help developers grow in their careers.

项目地址:https://gitcode.com/GitHub_Trending/de/developer-roadmap
点击查看免费下载

WebSockets 是 ASP.NET Core 实时通信能力的基础协议层,它通过单个 TCP 连接在客户端与服务器之间建立持久、全双工的通信通道。本文围绕 developer-roadmap 仓库中 web-sockets 主题卡片 的核心内容展开,讲解 WebSocket 协议的关键机制、ASP.NET Core 中间件在握手与连接管理中的角色,并给出可落地的服务端接入与消息收发方案,帮助你为聊天平台、实时仪表盘或协作类应用构建低延迟的推送通道。

WebSockets 是什么:在单个 TCP 连接上的全双工通道

WebSockets 提供了一种持久化(persistent)、全双工(full-duplex)的通信通道,它运行在客户端与服务器之间的单个 TCP 连接之上。这与传统 HTTP 的"请求—响应"模型有本质区别:

  • 传统 HTTP:每次交互都是一次独立请求,服务器只能在收到请求后返回响应,客户端若想获取最新数据必须反复主动发起请求(轮询)。
  • WebSocket:连接建立后保持打开,服务器可以主动向已连接的客户端推送更新,无需等待客户端请求,也无需客户端反复轮询。

正如关联文档所述,这一特性使 WebSocket 特别适合聊天平台、实时仪表盘、协作工具这类需要即时数据更新的应用场景——服务器一旦产生新消息或新状态,可以立即推送给所有相关客户端。

在 ASP.NET Core 中,中间件(Middleware)承担了两项关键职责:处理 WebSocket握手(handshake),以及管理持续的连接生命周期。中间件是 ASP.NET Core 请求管道的核心机制,每个组件在管道中依次执行,可参考仓库中的 Middlewares 主题;WebSocket 中间件正是在这个管道中拦截 Upgrade 请求并接管后续的实时通信。

握手过程:从 HTTP 升级到 WebSocket

WebSocket 连接并非凭空建立,它必须经过一次基于 HTTP 的升级握手:

  1. 客户端向服务器发送一个包含Upgrade: websocket和Connection: Upgrade头部的普通 HTTP 请求;
  2. 服务器若同意升级,返回 HTTP101 Switching Protocols状态码;
  3. 此后,该 TCP 连接上的通信协议切换为 WebSocket 帧协议,进入持久、全双工的数据交换阶段。

在 ASP.NET Core 中,这一握手由UseWebSockets()中间件触发:中间件检测到传入请求带有 WebSocket 升级头时,将其从常规 HTTP 管道中接管,后续代码再通过AcceptWebSocketAsync()正式接受连接。若请求不是合法的 WebSocket 请求(例如普通的 HTTP GET),则走常规管道继续处理或返回错误状态。

在 ASP.NET Core 中启用 WebSocket 中间件

以下代码遵循 ASP.NET Core 官方 WebSocket 支持文档(关联文档引用的学习资源)所描述的通用接入模式,可在你自己的 .NET 项目中实践(以你项目实际使用的 ASP.NET Core 版本为准,示例基于 .NET 6+ 的统一启动方式):

var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); // 1. 将 WebSocket 中间件加入请求管道(需在路由/终结点之前注册) app.UseWebSockets(); // 2. 定义处理 WebSocket 请求的端点 app.Map("/ws", async context => { // 判断是否为合法的 WebSocket 升级请求 if (context.WebSockets.IsWebSocketRequest) { // 3. 接受握手,拿到代表持久连接的 WebSocket 对象 using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); // 4. 进入收发消息的循环(见下一节) await EchoLoop(webSocket); } else { context.Response.StatusCode = StatusCodes.Status400BadRequest; } }); app.Run();

要点说明:

  • app.UseWebSockets()的位置:中间件按注册顺序执行,WebSocket 中间件应放在终结点路由之前,确保握手请求能被正确拦截。
  • IsWebSocketRequest:用于检查当前请求是否携带 WebSocket 升级头,避免把普通请求误当作 WebSocket 处理。
  • AcceptWebSocketAsync():完成握手并返回WebSocket实例,此后即可用该实例收发数据。
  • using声明:WebSocket实现了IDisposable,连接结束后应释放底层资源。

消息收发循环:ReceiveAsync 与 SendAsync

握手完成后,通信变成了"帧"级别的双向读写。服务端通常进入一个持续循环:不断调用ReceiveAsync等待客户端消息,再根据需要调用SendAsync回写数据。下面是一个典型的 echo(回声)服务实现,沿用 ASP.NET Core 标准的WebSocketAPI:

static async Task EchoLoop(WebSocket webSocket) { var buffer = new byte[1024 * 4]; while (webSocket.State == WebSocketState.Open) { // 接收一帧数据 var result = await webSocket.ReceiveAsync( new ArraySegment<byte>(buffer), CancellationToken.None); // 客户端发起关闭帧时,回送关闭并结束循环 if (result.MessageType == WebSocketMessageType.Close) { await webSocket.CloseAsync( WebSocketCloseStatus.NormalClosure, "Closed by client", CancellationToken.None); break; } // 将收到的内容原样发回 await webSocket.SendAsync( new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None); } }

关键点:

  • WebSocketState.Open:通过状态机判断连接是否仍然有效,是循环退出的依据。
  • ReceiveAsync/SendAsync:均为异步方法,底层基于单个 TCP 连接上的帧收发,天然支持服务器主动推送——服务器可以在任意时刻调用SendAsync,把新事件推给客户端。
  • WebSocketMessageType.Close:WebSocket 使用显式的关闭帧结束会话,客户端或服务器任一方都可发起。

WebSocket 与 HTTP 的取舍

关联文档在"进一步学习"中明确将WebSocket vs HTTP作为核心议题。两者的适用边界可以这样概括:

维度传统 HTTP(含轮询)WebSocket
连接每次请求独立、短连接单个 TCP 连接、持久保持
方向请求—响应,客户端驱动全双工,服务器可主动推送
实时性依赖轮询间隔,存在延迟即时推送,延迟低
适用场景常规网页、REST API聊天、实时仪表盘、协作、在线游戏

需要说明的是:WebSocket 的"全双工 + 服务器推送"能力,正是仓库中 Real-Time Communication 主题 所描述的实时通信需求——客户端无需不断请求更新,服务器即可即时推送内容(如实时通知、聊天消息、数据看板刷新)——的底层协议支撑。

WebSockets 与 SignalR:何时使用哪个

在 ASP.NET Core 的实时通信体系中,WebSocket 与 SignalR 是"底层能力"与"高层抽象"的关系:

  • WebSocket:协议级别的实现,需要你自行处理握手、连接管理、消息帧解析、断线重连、广播逻辑等细节。
  • SignalR Core:基于 WebSocket 之上的封装库,自动管理连接,并在 WebSocket 不可用时自动降级到 Server-Sent Events 或 Long Polling等兼容技术,让开发者专注于业务逻辑(如IHubContext推送、分组、强类型客户端),参见仓库中的 SignalR Core 主题。

因此实践上的建议是:需要精确控制底层帧、或只需一对一的原始 WebSocket 通道时,直接使用 WebSocket 中间件;需要聊天室广播、断线重连、跨技术降级等开箱能力时,优先选择 SignalR。两者在 ASP.NET Core 中可以共存于同一应用。

典型应用场景

关联文档明确列举了三类典型场景,均可基于 WebSocket 中间件落地:

  1. 聊天平台:服务器把每条新消息实时推送给同一会话的所有客户端,无需刷新页面;
  2. 实时仪表盘:监控指标、交易行情、系统日志等数据变化时,服务器即时推送刷新,客户端保持低延迟展示;
  3. 协作工具:多用户同时编辑文档、白板或看板时,一方的操作实时同步到其他参与者。

这些场景的共同点是"服务器有状态变化需要主动告知客户端",恰好命中 WebSocket 的推送模型。若结合仓库的 Minimal APIs 主题 所介绍的精简端点风格,用少量代码即可在一个轻量服务中挂载/ws这样的 WebSocket 端点,与常规 REST 端点共存。

生产环境中的注意事项

在真实项目中启用 WebSocket 时,还需要关注以下几点(这些是 ASP.NET Core 官方 WebSocket 支持文档中强调的通用事项,最终以你所用框架版本的文档为准):

  • 代理与负载均衡:WebSocket 依赖长连接与 Upgrade 头,经过反向代理(如 Nginx、IIS、YARP 等)时必须显式开启 WebSocket 代理支持,并合理设置超时,否则连接可能被意外断开;
  • 心跳保活(Keep-Alive):中间件通过WebSocketOptions.KeepAliveInterval控制 ping 帧的发送间隔,防止空闲连接被网络设备回收;
  • 并发与背压:大量客户端连接会占用文件描述符与内存,广播时应采用异步写入并考虑背压控制,避免慢客户端拖慢整体推送;
  • 安全性:WebSocket 请求同样受认证/授权中间件约束,握手阶段即可完成身份校验;对跨域场景需配置允许的来源(AllowedOrigins),防止任意站点建立连接。

小结

WebSockets 为 ASP.NET Core 应用带来了单个 TCP 连接上的持久、全双工实时通信能力:UseWebSockets()中间件负责握手与连接管理,AcceptWebSocketAsync()完成升级,ReceiveAsync/SendAsync支撑双向帧收发,服务器得以即时向客户端推送更新。它适合聊天、实时仪表盘与协作工具等场景,而在需要广播、重连与协议降级等更高层能力时,可将 SignalR 视为 WebSocket 之上的首选抽象。结合本仓库 aspnet-core roadmap 的主题脉络,你可以从 WebSocket 协议层出发,逐步构建完整的实时应用栈。

  • 文档
  • 教程
  • 知识库

【免费下载链接】developer-roadmap

Interactive roadmaps, guides and other educational content to help developers grow in their careers.

项目地址:https://gitcode.com/GitHub_Trending/de/developer-roadmap
点击查看免费下载
上一篇:Hugo 模板函数 inflect.Pluralize 完全指南:英文单词复数化的语法、实现与实战用法
下一篇:ik_llama.cpp 在 RTX 5090(Compute Capability 12.0)上的 CUDA 内核兼容性排障实录:从 "no kernel image" 到多卡集群实战

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询