引言:为什么WebSocket是实时应用程序的标准?
现代Web应用程序需要对用户操作做出即时响应。无论是在线聊天、股票交易终端、多人在线游戏还是监控系统——数据传输的延迟都是不可接受的。传统的HTTP协议基于“请求-响应”模式,对于此类场景效率低下:客户端必须不断轮询服务器,造成不必要的负载。
WebSocket应运而生——这是一种在客户端和服务器之间提供持久双向连接的协议。在本文中,我们将探讨如何使用C#(.NET)创建实时应用程序,从简单的回显服务器到完整的聊天系统。您将了解协议的工作原理、.NET平台提供的工具,以及如何避免常见错误。
.NET中WebSocket的基础:服务器端
.NET平台通过System.Net.WebSockets命名空间提供对WebSocket的内置支持。让我们看看如何基于ASP.NET Core创建服务器。
1. 配置WebSocket中间件
首先,需要在请求处理管道中添加WebSocket支持。在Program.cs文件中:
var builder = WebApplication.CreateBuilder(args);var app = builder.Build();
app.UseWebSockets(); // 启用WebSocket支持
app.Map("/ws", async (HttpContext context) =>{ if (context.WebSockets.IsWebSocketRequest) { using var webSocket = await context.WebSockets.AcceptWebSocketAsync(); await Echo(webSocket); } else { context.Response.StatusCode = 400; }});
app.Run("http://localhost:5000");
async Task Echo(WebSocket webSocket){ var buffer = new byte[1024 * 4]; var receiveResult = await webSocket.ReceiveAsync( new ArraySegment<byte>(buffer), CancellationToken.None);
while (!receiveResult.CloseStatus.HasValue) { // 将接收到的数据发送回客户端(回显) await webSocket.SendAsync( new ArraySegment<byte>(buffer, 0, receiveResult.Count), receiveResult.MessageType, receiveResult.EndOfMessage, CancellationToken.None);
receiveResult = await webSocket.ReceiveAsync( new ArraySegment<byte>(buffer), CancellationToken.None); }
await webSocket.CloseAsync( receiveResult.CloseStatus.Value, receiveResult.CloseStatusDescription, CancellationToken.None);}这段代码创建了一个回显服务器:客户端发送的所有内容都会被返回。请注意使用async/await——与WebSocket的交互始终是异步的。
2. 管理多个连接
在实际应用程序中,需要管理多个连接。让我们创建一个简单的连接管理器:
public class WebSocketConnectionManager{ private readonly ConcurrentDictionary<string, WebSocket> _connections = new();
public string AddConnection(WebSocket socket) { var id = Guid.NewGuid().ToString(); _connections.TryAdd(id, socket); return id; }
public async Task BroadcastMessageAsync(string message) { var tasks = _connections.Values.Select(async socket => { if (socket.State == WebSocketState.Open) { var bytes = Encoding.UTF8.GetBytes(message); await socket.SendAsync( new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None); } }); await Task.WhenAll(tasks); }}这个类允许存储所有活动连接并广播消息