From f47e512d026d6e49482b58f1e87af0f8c0e853ff Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Wed, 19 Aug 2026 10:54:27 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=9B=B4=E6=96=B0.net=E7=BD=91=E7=BB=9C?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/Web/Network/NetCore.md | 83 ++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/docs/Web/Network/NetCore.md b/docs/Web/Network/NetCore.md index dec36fa..d51ca1c 100644 --- a/docs/Web/Network/NetCore.md +++ b/docs/Web/Network/NetCore.md @@ -54,6 +54,7 @@ var host = Host.CreateDefaultBuilder(args) { services.AddSingleton, TcpPackageHandler>(); services.AddSingleton(); + services.AddSingleton(); // 1. 注入 MQTT 配置 services.Configure(context.Configuration.GetSection("Mqtt")); @@ -70,6 +71,26 @@ var host = Host.CreateDefaultBuilder(args) .AddWebSocketServer(builder => { builder + .UseSessionHandler( + session => + { + if (session is WebSocketSession wsSession) + { + var connectionManager = session.Server.ServiceProvider.GetRequiredService(); + connectionManager.Add(wsSession); + } + return ValueTask.CompletedTask; + }, + (session, reason) => + { + if (session is WebSocketSession wsSession) + { + var connectionManager = session.Server.ServiceProvider.GetRequiredService(); + connectionManager.Remove(wsSession); + } + return ValueTask.CompletedTask; + } + ) .UseWebSocketMessageHandler(async (session, package) => { using var scope = session.Server.ServiceProvider.CreateScope(); @@ -198,8 +219,34 @@ class TcpPackageHandler(ILogger logger) : IPackageHandler serverOptions) : SuperSocketService(serviceProvider, serverOptions) +class TcpService(IServiceProvider serviceProvider, IOptions serverOptions, ILogger logger) : SuperSocketService(serviceProvider, serverOptions) { + private readonly ILogger _logger = logger; + + private readonly ConcurrentDictionary _sessionDevices = new(); + + public void BindDevice(string sessionId, string deviceNum) + { + _sessionDevices.AddOrUpdate(sessionId, deviceNum, (k, v) => deviceNum); + } + + protected override async ValueTask OnSessionConnectedAsync(IAppSession session) + { + _logger.LogInformation("TCP Session 连上: {SessionID}", session.SessionID); + await base.OnSessionConnectedAsync(session); + } + + protected override async ValueTask OnSessionClosedAsync(IAppSession session, CloseEventArgs e) + { + _logger.LogInformation("TCP Session 断开: {SessionID}, Reason={Reason}", session.SessionID, e.Reason); + + if (_sessionDevices.TryRemove(session.SessionID, out var deviceNum)) + { + _logger.LogInformation("设备 {DeviceNum} 标记离线", deviceNum); + } + + await base.OnSessionClosedAsync(session, e); + } } ``` @@ -218,6 +265,40 @@ class WebSocketMessageHandler(ILogger logger) } ``` +## 3.2 连接管理 +```cs +public class WebSocketConnectionManager(ILogger logger) +{ + private readonly ConcurrentDictionary _sessions = new(); + private readonly ILogger _logger = logger; + + public void Add(WebSocketSession session) => _sessions.TryAdd(session.SessionID, session); + + public void Remove(WebSocketSession session) => _sessions.TryRemove(session.SessionID, out _); + + public async Task BroadcastAsync(string json) + { + var payload = new ReadOnlyMemory(System.Text.Encoding.UTF8.GetBytes(json)); + + var tasks = _sessions.Values + .Where(s => s.State == SessionState.Connected) + .Select(async s => + { + try + { + await s.SendAsync(json); + } + catch + { + Remove(s); + } + }); + + await Task.WhenAll(tasks); + } +} +``` + # 四、 MQTT服务器 ## 4.1 MqttService ```cs