158 lines
6.0 KiB
C#
158 lines
6.0 KiB
C#
using CrasyStudio.Core.Common.Redis.Dto;
|
||
using CrasyStudio.Core.Common.Status;
|
||
using CrasyStudio.Core.Common.Status.Eitities;
|
||
using Fleck;
|
||
using MessagePack;
|
||
using NanoidDotNet;
|
||
|
||
namespace CGamesServer.Api.WebServers
|
||
{
|
||
public class GameServer
|
||
{
|
||
//private const int BufferSize = 1024;
|
||
//private HttpListener _httpListener;
|
||
//private bool isRunning = false;
|
||
|
||
//public GameServer(string domain)
|
||
//{
|
||
// _httpListener = new HttpListener();
|
||
// _httpListener.Prefixes.Add(domain);
|
||
//}
|
||
|
||
//public async Task Start()
|
||
//{
|
||
// this.isRunning = true;
|
||
// _httpListener.Start();
|
||
// Console.WriteLine($"WebSocket server started. Listening on {_httpListener.Prefixes.FirstOrDefault()}");
|
||
|
||
// while (isRunning)
|
||
// {
|
||
// var context = await _httpListener.GetContextAsync();
|
||
// if (context.Request.IsWebSocketRequest)
|
||
// {
|
||
// var webSocketContext = await context.AcceptWebSocketAsync(null);
|
||
// await HandleWebSocketConnection(webSocketContext.WebSocket);
|
||
// }
|
||
// else
|
||
// {
|
||
// context.Response.StatusCode = 400;
|
||
// context.Response.Close();
|
||
// }
|
||
// }
|
||
//}
|
||
|
||
//public void Stop()
|
||
//{
|
||
// this.isRunning = false;
|
||
// _httpListener.Stop();
|
||
// Console.WriteLine("WebSocket server stopped.");
|
||
//}
|
||
|
||
//private async Task HandleWebSocketConnection(WebSocket webSocket)
|
||
//{
|
||
// var buffer = new byte[BufferSize];
|
||
// var receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||
|
||
// while (!receiveResult.CloseStatus.HasValue)
|
||
// {
|
||
// var message = Encoding.UTF8.GetString(buffer, 0, receiveResult.Count);
|
||
// Console.WriteLine($"Received: {message}");
|
||
|
||
// var responseMessage = $"Server received: {message}";
|
||
// var responseBuffer = Encoding.UTF8.GetBytes(responseMessage);
|
||
// await webSocket.SendAsync(new ArraySegment<byte>(responseBuffer), WebSocketMessageType.Text, true, CancellationToken.None);
|
||
|
||
// receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||
// }
|
||
|
||
// await webSocket.CloseAsync(receiveResult.CloseStatus.Value, receiveResult.CloseStatusDescription, CancellationToken.None);
|
||
//}
|
||
|
||
private readonly ClusterOnlineUsers _onlineUsers;
|
||
private readonly NetEventRegister _netEventRegister;
|
||
|
||
public GameServer(ClusterOnlineUsers onlineUsers, NetEventRegister netEventRegister)
|
||
{
|
||
this._onlineUsers = onlineUsers;
|
||
this._netEventRegister = netEventRegister;
|
||
}
|
||
|
||
public void Start(int webServerPort)
|
||
{
|
||
FleckLog.Level = Fleck.LogLevel.Error;
|
||
// 启动Fleck WebSocket服务器(独立线程)
|
||
var webSocketServer = new WebSocketServer($"ws://0.0.0.0:{webServerPort}");
|
||
//var webSocketServer = new WebSocketServer($"wss://0.0.0.0:{webServerPort}");
|
||
//webSocketServer.Certificate = new X509Certificate2("MyCert.pfx");
|
||
|
||
webSocketServer.ListenerSocket.NoDelay = true;//禁用Nagle算法,增加实时性,但是会使流量变大,适合小包高频率发送
|
||
webSocketServer.Start(InitWebSocketConnection);
|
||
}
|
||
|
||
public void InitWebSocketConnection(IWebSocketConnection socket)
|
||
{
|
||
int checkDisconnectForHeartBeatCount = 0;
|
||
var user = new OnlineUserInfo
|
||
{
|
||
Socket = socket
|
||
};
|
||
Timer heartBeatTimer = new Timer((state) =>
|
||
{
|
||
if (user.HeartBeatDurationMs == -1)
|
||
{
|
||
return;
|
||
}
|
||
checkDisconnectForHeartBeatCount++;
|
||
if (checkDisconnectForHeartBeatCount > 3)
|
||
{
|
||
socket.Close();
|
||
//Console.WriteLine($"心跳包超时,关闭连接: {socket.ConnectionInfo.ClientIpAddress}");
|
||
}
|
||
});
|
||
|
||
//这里生成ConnectionId
|
||
string connectionId = Nanoid.Generate(); //Guid.NewGuid().ToString("N");
|
||
socket.OnOpen = async () =>
|
||
{
|
||
heartBeatTimer.Change(0, 1000);
|
||
//Console.WriteLine("WebSocket连接建立");
|
||
await _onlineUsers.AddOrUpdateUser(connectionId, user);
|
||
};
|
||
socket.OnClose = async () =>
|
||
{
|
||
heartBeatTimer.Dispose();
|
||
user.HeartBeatDurationMs = -1;//连接断开,修正心跳包检测时间为不需要
|
||
await _onlineUsers.RemoveUserFromId(connectionId);
|
||
//Console.WriteLine("WebSocket连接关闭");
|
||
};
|
||
socket.OnError = (ex) =>
|
||
{
|
||
//await _onlineUsers.RemoveUserFromId(connectionId);
|
||
//Console.WriteLine("WebSocket错误:" + ex.Message + ":StackTrace:" + ex.StackTrace);
|
||
};
|
||
|
||
socket.OnBinary = async message =>
|
||
{
|
||
checkDisconnectForHeartBeatCount = 0;
|
||
//Console.WriteLine($"收到消息: {message}");
|
||
try
|
||
{
|
||
var baseMessage = MessagePackSerializer.Deserialize<BaseMessage>(message);
|
||
await _netEventRegister.InvokeEvent(baseMessage.MsgType, connectionId, baseMessage);
|
||
}
|
||
catch (MessagePackSerializationException ex)
|
||
{
|
||
Console.WriteLine($"反序列化消息错误: {ex.Message}");
|
||
socket.Close();
|
||
}
|
||
//socket.Send(message); // 回显消息
|
||
};
|
||
|
||
socket.OnMessage = (message) =>
|
||
{
|
||
checkDisconnectForHeartBeatCount = 0;
|
||
};
|
||
}
|
||
}
|
||
}
|