IIS 中使用 WebSocket
下面将介绍如何在iis上使用 websocket 。
创建项目
我们需要创建一个 WebApi
打开初始程序中 Program 类的 main 方法,并进行修改
服务器 - 添加管理类
创建一个管理类用于管理 WebSocket 的链接

1 public class WebSocketConnectionManager 2 { 3 private Dictionary<string, WebSocket> connections = new Dictionary<string, WebSocket>(); 4 private int onlineUserCount = 0; 5 6 //检测到链接时加入列表 7 public void AddWebSocket(WebSocket webSocket) 8 { 9 string connectionId = Guid.NewGuid().ToString(); 10 connections.TryAdd(connectionId, webSocket); 11 } 12 13 //断开链接时移除列表中数据 14 public void RemoveWebSocket(WebSocket webSocket) 15 { 16 var connection = connections.FirstOrDefault(pair => pair.Value == webSocket); 17 if (!connection.Equals(default(KeyValuePair<string, WebSocket>))) 18 { 19 connections.Remove(connection.Key); 20 } 21 } 22 23 //获取当前连接数 24 public int GetOnlineUserCount() 25 { 26 return onlineUserCount; 27 } 28 29 //链接计数器 30 public void IncrementOnlineUserCount() 31 { 32 onlineUserCount++; 33 } 34 public void DecrementOnlineUserCount() 35 { 36 if (onlineUserCount > 0) 37 { 38 onlineUserCount--; 39 } 40 } 41 }
将管理类以单例的方式添加到服务列表中
方便在控制器中调用,调用方法如下

1 [ApiController] 2 [Route("[controller]")] 3 public class WebSocketController : ControllerBase 4 { 5 private readonly WebSocketConnectionManager _webSocketConnectionManager; 6 public WebSocketController(WebSocketConnectionManager webSocketConnectionManager) 7 { 8 _webSocketConnectionManager = webSocketConnectionManager; 9 } 10 11 [HttpGet] 12 [Route("ConnectionNum")] 13 public IActionResult ConnectionNum() 14 { 15 int onlineUserCount = _webSocketConnectionManager.GetOnlineUserCount(); 16 17 return Ok("WebSocket API Connect Num - " + onlineUserCount); 18 } 19 }
服务器 - 在 IIS 中添加 WebSocket
如需在服务器上使用 WebSocket ,需服务器管理器中添加 WebSocket 协议
继续在 Program 类的 main 方法 添加代码

var app = builder.Build(); //获取 WebSocekets 并将 管理 加入到 Websocket处理中 WebSocketHandler webSocketHandler = new WebSocketHandler(app.Services.GetRequiredService<WebSocketConnectionManager>()); //WebSockets 选项 (可忽略使用默认值) WebSocketOptions options = new WebSocketOptions(); options.KeepAliveInterval = TimeSpan.FromSeconds(120); options.ReceiveBufferSize = 4 * 1024; app.UseWebSockets(options); app.Use(async (context, next) => { if (context.WebSockets.IsWebSocketRequest) { //走自己处理 WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); await webSocketHandler.HandleWebSocketAsync(webSocket); } else { //走控制器 await next(); } });
WebSocketHandler 类

public class WebSocketHandler { private WebSocket webSocket; private WebSocketConnectionManager connectionManager; public WebSocketHandler(WebSocketConnectionManager connectionManager) { this.connectionManager = connectionManager; } public async Task HandleWebSocketAsync(WebSocket socket) { this.webSocket = socket; this.connectionManager.AddWebSocket(webSocket); // 连接成功后,增加在线用户数量 connectionManager.IncrementOnlineUserCount(); try { byte[] buffer = new byte[1024]; WebSocketReceiveResult result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); while (!result.CloseStatus.HasValue) { string message = Encoding.UTF8.GetString(buffer, 0, result.Count); Console.WriteLine($"Received: {message}"); // Process and respond to the message here await socket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None); result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None); } if (result.CloseStatus.HasValue) { CloseWebSocket(); await socket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); } } catch (Exception ex) { try { // 指定要写入的文件路径 string executablePath = System.Reflection.Assembly.GetEntryAssembly().Location; string executableDirectory = Path.GetDirectoryName(executablePath); string fileName = "error.log"; // 文件名 string filePath = Path.Combine(executableDirectory, fileName); if (!File.Exists(filePath)) { using (File.Create(filePath)) { // 文件流在这个块内创建并打开,随后会在块结束时自动关闭。 } } // 使用 StreamWriter 打开文件以追加方式写入错误信息 using (StreamWriter writer = File.AppendText(filePath)) { // 写入错误信息和时间戳 writer.WriteLine($"[{DateTime.Now}] {ex.Message}"); } } catch (Exception) { // 处理可能的文件操作异常 Console.WriteLine("写入错误日志时发生异常:" + ex.Message); } CloseWebSocket(); } } private void CloseWebSocket() { if (this.webSocket != null) { this.connectionManager.RemoveWebSocket(this.webSocket); // 断开连接后,减少在线用户数量 connectionManager.DecrementOnlineUserCount(); this.webSocket.Dispose(); } } }
客户端 - WebSocket 链接请求
代码示例

public class WebSocketApi { static Uri clientUri = new Uri("wss://www.lilongfei.club:1994"); // WebSocket server address https 使用 //static Uri clientUri = new Uri("ws://www.lilongfei.club:1994"); // WebSocket server address http 使用 static ClientWebSocket clientWebSocket = new ClientWebSocket(); #region 客户端 IIS public static async Task WebSocketStart() { try { //只进行一次链接请求 if (clientWebSocket.State != WebSocketState.Open) { //将代理器设为空 clientWebSocket.Options.Proxy = null; //链接 IIS服务器 await clientWebSocket.ConnectAsync(clientUri, CancellationToken.None); } Console.WriteLine("Connected to the WebSocket server."); // Send a message to the server string messageToSend = "Hello, server!"; byte[] sendBuffer = Encoding.UTF8.GetBytes(messageToSend); await clientWebSocket.SendAsync(new ArraySegment<byte>(sendBuffer), WebSocketMessageType.Text, true, CancellationToken.None); // Receive and handle the server's response byte[] receiveBuffer = new byte[1024]; WebSocketReceiveResult receiveResult = await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), CancellationToken.None); string receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, receiveResult.Count); Console.WriteLine($"Received: {receivedMessage}"); } catch (Exception e) { await CloseWebSocket(clientWebSocket); Console.WriteLine(e); throw; } } //关闭 WebSocket 链接 static async Task CloseWebSocket(ClientWebSocket clientWebSocket) { byte[] closeBuffer = Encoding.UTF8.GetBytes("Connection closing..."); WebSocketCloseStatus closeStatus = WebSocketCloseStatus.NormalClosure; string closeDescription = "Connection closed gracefully"; CancellationToken ct = CancellationToken.None; await clientWebSocket.CloseOutputAsync(closeStatus, closeDescription, ct); WebSocketReceiveResult result = await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(new byte[1024]), ct); await clientWebSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, ct); } #endregion
完成收工
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)