This commit is contained in:
wuyanchen 2025-12-30 11:22:46 +08:00
parent fd60b1cea5
commit 84d98d54d4
4 changed files with 40 additions and 16 deletions

View File

@ -0,0 +1,11 @@
using System.Collections.Concurrent;
using System.Net.WebSockets;
namespace XNet.Business.Entity
{
public class WebSocketInfo
{
public WebSocket WebSocket { get; set; } = null!;
public ConcurrentDictionary<string, bool> RoomIds { get; set; } = new();
}
}

View File

@ -6,6 +6,7 @@ using System.Diagnostics;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Text.Json;
using XNet.Business.Entity;
using XNet.Business.PathNavigation;
namespace XNet.Business.Net
@ -13,7 +14,7 @@ namespace XNet.Business.Net
public class WsConnectionManager
{
// ========== 原有核心字段 ==========
private readonly ConcurrentDictionary<string, WebSocket> _connections = new();
private readonly ConcurrentDictionary<string, WebSocketInfo> _connections = new();
private readonly ConcurrentDictionary<string, ConcurrentDictionary<string, bool>> _instanceSubscribers = new();
//private readonly JsonSerializerOptions _jsonOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase };
@ -23,7 +24,7 @@ namespace XNet.Business.Net
private readonly ObjectPool<List<string>> _deadConnListPool;
private readonly ObjectPool<byte[]> _byteArrayPool;
private readonly SceneAgent _sceneAgent = null;
private readonly SceneAgent _sceneAgent = null!;
public WsConnectionManager(SceneAgent sceneAgent)
{
@ -41,16 +42,19 @@ namespace XNet.Business.Net
public string AddConnection(WebSocket socket)
{
string connId = $"Conn_{Nanoid.Generate()}";
_connections.TryAdd(connId, socket);
_connections.TryAdd(connId, new WebSocketInfo
{
WebSocket = socket
});
Console.WriteLine($"[WS .NET 10] 新连接:{connId},当前连接数:{_connections.Count}");
return connId;
}
public void RemoveConnection(string connId)
{
if (_connections.TryRemove(connId, out _))
if (_connections.TryRemove(connId, out var socketInfo))
{
foreach (var instanceId in _instanceSubscribers.Keys)
foreach (var instanceId in socketInfo.RoomIds.Keys)
{
_instanceSubscribers[instanceId].TryRemove(connId, out _);
@ -66,7 +70,7 @@ namespace XNet.Business.Net
public bool SubscribeInstance(string connId, string mapKey, ref string roomId)
{
if (!_connections.ContainsKey(connId))
if (!_connections.TryGetValue(connId,out WebSocketInfo? socketInfo))
{
Console.WriteLine($"[WS .NET 10] 订阅失败:连接 {connId} 不存在");
return false;
@ -88,6 +92,8 @@ namespace XNet.Business.Net
_instanceSubscribers[roomId].TryAdd(connId, true);
socketInfo.RoomIds[roomId] = true;
if (isNewInstance)
{
_sceneAgent.CreateInstance(roomId, mapKey);
@ -107,7 +113,7 @@ namespace XNet.Business.Net
public async Task SendSerializeMessageToPointWsSocket<T>(string connId, T syncMsgs)
{
if (_connections.TryGetValue(connId, out var socket))
if (_connections.TryGetValue(connId, out var socketInfo))
{
// 3. 复用:从池获取失效连接列表
var deadConnIds = _deadConnListPool.Get();
@ -117,12 +123,12 @@ namespace XNet.Business.Net
if (msgBytesLength != 0)
{
// 3. 发送时传递有效长度
_ = SendToSingleConnAsync(socket, msgBytes, msgBytesLength, connId, deadConnIds);
_ = SendToSingleConnAsync(socketInfo.WebSocket, msgBytes, msgBytesLength, connId, deadConnIds);
}
else
{
// 3. 发送整串字节数组
_ = SendToSingleConnAsync(socket, msgBytes, msgBytes.Length, connId, deadConnIds);
_ = SendToSingleConnAsync(socketInfo.WebSocket, msgBytes, msgBytes.Length, connId, deadConnIds);
}
// 清理失效连接
foreach (var deadConnId in deadConnIds)
@ -169,17 +175,17 @@ namespace XNet.Business.Net
{
foreach (var connKv in subscriberConnIds)
{
if (_connections.TryGetValue(connKv.Key, out var socket))
if (_connections.TryGetValue(connKv.Key, out var socketInfo))
{
if (msgBytesLength != 0)
{
// 3. 发送时传递有效长度
_ = SendToSingleConnAsync(socket, msgBytes, msgBytesLength, connKv.Key, deadConnIds);
_ = SendToSingleConnAsync(socketInfo.WebSocket, msgBytes, msgBytesLength, connKv.Key, deadConnIds);
}
else
{
// 3. 发送整串字节数组
_ = SendToSingleConnAsync(socket, msgBytes, msgBytes.Length, connKv.Key, deadConnIds);
_ = SendToSingleConnAsync(socketInfo.WebSocket, msgBytes, msgBytes.Length, connKv.Key, deadConnIds);
}
}
}
@ -284,13 +290,14 @@ namespace XNet.Business.Net
public async ValueTask DisposeAsync()
{
foreach (var (_, socket) in _connections)
foreach (var (key, socketInfo) in _connections)
{
if (socket.State == WebSocketState.Open)
if (socketInfo.WebSocket.State == WebSocketState.Open)
{
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Server shutdown", CancellationToken.None);
await socketInfo.WebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Server shutdown", CancellationToken.None);
}
socket.Dispose();
socketInfo.WebSocket.Dispose();
RemoveConnection(key);
}
_connections.Clear();
_instanceSubscribers.Clear();

View File

@ -39,6 +39,7 @@ namespace XNet.Business.Net
if (result.MessageType == WebSocketMessageType.Close)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by client", CancellationToken.None);
wsManager.RemoveConnection(connId);
break;
}

View File

@ -136,6 +136,11 @@ namespace XNet.Business.PathNavigation
_instanceMap.TryRemove(roomId, out _);
}
public void ClearInstanceMap()
{
_instanceMap.Clear();
}
// ==========================================
// 3. 【新增】供 SceneAgent 使用的辅助方法
// ==========================================