87 lines
3.6 KiB
C#
87 lines
3.6 KiB
C#
using MessagePack;
|
||
using System.Net.WebSockets;
|
||
using XNet.Business.PathNavigation;
|
||
using XNet.Business.Tank.Manager;
|
||
|
||
namespace XNet.Business.Net
|
||
{
|
||
public static class WsServer
|
||
{
|
||
private static ActionManager? ActionManager = null;
|
||
// 启动WebSocket监听
|
||
public static void MapWebSocketServer(this WebApplication app, WsConnectionManager wsManager, NavMeshManager navMeshManager, SceneAgent sceneAgent)
|
||
{
|
||
if (ActionManager == null)
|
||
{
|
||
ActionManager = new ActionManager(wsManager, navMeshManager, sceneAgent);
|
||
}
|
||
//初始化玩家设备列表
|
||
DeviceManager.Instance.Init();
|
||
app.Map("/ws", async context =>
|
||
{
|
||
if (!context.WebSockets.IsWebSocketRequest)
|
||
{
|
||
context.Response.StatusCode = StatusCodes.Status400BadRequest;
|
||
return;
|
||
}
|
||
|
||
// 建立WebSocket连接
|
||
using var webSocket = await context.WebSockets.AcceptWebSocketAsync();
|
||
string connId = wsManager.AddConnection(webSocket);
|
||
|
||
// 【修改点1】单条消息的缓冲区,用MemoryStream接收分片数据,自动扩容
|
||
var receiveBuffer = new byte[1024 * 4];
|
||
var ms = new MemoryStream();
|
||
try
|
||
{
|
||
while (webSocket.State == WebSocketState.Open)
|
||
{
|
||
var result = await webSocket.ReceiveAsync(receiveBuffer, CancellationToken.None);
|
||
|
||
// 1. 客户端主动关闭连接
|
||
if (result.MessageType == WebSocketMessageType.Close)
|
||
{
|
||
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closed by client", CancellationToken.None);
|
||
await wsManager.RemoveConnection(connId);
|
||
break;
|
||
}
|
||
|
||
// 2. 忽略空消息/心跳包
|
||
if (result.Count == 0) continue;
|
||
|
||
// 3. 【核心修复】将本次收到的分片数据,写入MemoryStream,拼接完整消息
|
||
ms.Write(receiveBuffer, 0, result.Count);
|
||
|
||
// 4. 【核心修复】判断是否是完整消息的最后分片
|
||
if (result.EndOfMessage)
|
||
{
|
||
// 重置流的指针到起始位置,准备反序列化
|
||
ms.Position = 0;
|
||
|
||
byte[] data1 = ms.ToArray();
|
||
// 反序列化完整的消息
|
||
var wsMsg = MessagePackSerializer.Deserialize<BaseMsg>(data1);
|
||
if (wsMsg != null)
|
||
{
|
||
// 执行你的业务逻辑,异步无等待
|
||
_ = ActionManager.ExecuteAction(wsMsg.Type, connId, wsMsg.Data!);
|
||
}
|
||
// 清空流,准备接收下一条消息
|
||
ms.SetLength(0);
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Console.WriteLine($"[WS] 连接 {connId} 异常:{ex.Message}");
|
||
}
|
||
finally
|
||
{
|
||
// 释放资源 + 移除连接
|
||
ms.Dispose();
|
||
await wsManager.RemoveConnection(connId);
|
||
}
|
||
});
|
||
}
|
||
}
|
||
} |