- 文档
- 教程
- 知识库
【免费下载链接】developer-roadmap
Interactive roadmaps, guides and other educational content to help developers grow in their careers.
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 的升级握手:
- 客户端向服务器发送一个包含
Upgrade: websocket和Connection: Upgrade头部的普通 HTTP 请求; - 服务器若同意升级,返回 HTTP
101 Switching Protocols状态码; - 此后,该 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 中间件落地:
- 聊天平台:服务器把每条新消息实时推送给同一会话的所有客户端,无需刷新页面;
- 实时仪表盘:监控指标、交易行情、系统日志等数据变化时,服务器即时推送刷新,客户端保持低延迟展示;
- 协作工具:多用户同时编辑文档、白板或看板时,一方的操作实时同步到其他参与者。
这些场景的共同点是"服务器有状态变化需要主动告知客户端",恰好命中 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.
相关推荐
Convex Backend与WebSockets:实现全双工通信的终极指南
Convex Backend与WebSockets:实现全双工通信的终极指南 Convex Backend是一个开源的单机版后端解决方案,它通过WebSocke
数据库后端5分钟上手Alpine.js实时通信:WebSockets实战指南
5分钟上手Alpine.js实时通信:WebSockets实战指南 你还在为实现网页实时数据更新而编写复杂的JavaScript代码吗?是否觉得WebSocke
前端ASP.NET Core全局异常处理的终极指南:IExceptionHandler中间件实战
ASP.NET Core全局异常处理的终极指南:IExceptionHandler中间件实战 在ASP.NET Core应用开发中, 全局异常处理 是保障应用稳
示例工程
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考