milimoe d23c6597d1
完善 HTTPClient;添加日志级别;添加匿名服务器模组;修复不同时间多客户端连接游戏模组时可能产生的线程安全问题 (#106)
* 完善 HTTPClient;添加日志级别;添加匿名服务器模组(此模组不强制要求登录、客户端安装)

* 添加参数

* 添加 null 检查

* 修复不同时间多客户端连接游戏模组时可能产生的线程安全问题
2025-01-17 18:58:51 +08:00

121 lines
3.8 KiB
C#

using Milimoe.FunGame.Core.Interface.Sockets;
using Milimoe.FunGame.Core.Library.Common.Architecture;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.Exception;
using Milimoe.FunGame.Core.Service;
namespace Milimoe.FunGame.Core.Library.Common.Network
{
public class Socket : IClientSocket
{
public System.Net.Sockets.Socket Instance { get; }
public SocketRuntimeType Runtime => SocketRuntimeType.Client;
public Guid Token { get; set; } = Guid.Empty;
public string ServerAddress { get; } = "";
public int ServerPort { get; } = 0;
public string ServerName { get; } = "";
public string ServerNotice { get; } = "";
public bool Connected => Instance != null && Instance.Connected;
public bool Receiving => _receiving;
private HeartBeat HeartBeat { get; }
public event Action<System.Exception>? ConnectionLost;
public event Action? Closed;
private Task? _receivingTask;
private bool _receiving = false;
private readonly HashSet<Action<SocketObject>> _boundEvents = [];
private Socket(System.Net.Sockets.Socket instance, string serverAddress, int serverPort)
{
this.Instance = instance;
this.ServerAddress = serverAddress;
this.ServerPort = serverPort;
HeartBeat = new(this);
HeartBeat.StartSendingHeartBeat();
}
public static Socket Connect(string address, int port = 22222)
{
System.Net.Sockets.Socket? socket = SocketManager.Connect(address, port);
if (socket != null) return new Socket(socket, address, port);
else throw new ConnectFailedException();
}
public SocketResult Send(SocketMessageType type, params object[] objs)
{
if (Instance != null)
{
if (SocketManager.Send(new(type, Token, objs)) == SocketResult.Success)
{
return SocketResult.Success;
}
return SocketResult.Fail;
}
return SocketResult.NotSent;
}
public SocketObject[] Receive()
{
try
{
SocketObject[] result = SocketManager.Receive();
return result;
}
catch (System.Exception e)
{
OnConnectionLost(e);
Close();
Api.Utility.TXTHelper.AppendErrorLog(e.GetErrorInfo());
throw new SocketWrongInfoException();
}
}
public void AddSocketObjectHandler(Action<SocketObject> method)
{
if (_boundEvents.Add(method))
{
SocketManager.SocketReceive += new SocketManager.SocketReceiveHandler(method);
}
}
public void RemoveSocketObjectHandler(Action<SocketObject> method)
{
_boundEvents.Remove(method);
SocketManager.SocketReceive -= new SocketManager.SocketReceiveHandler(method);
}
public void OnConnectionLost(System.Exception e)
{
ConnectionLost?.Invoke(e);
}
public void Close()
{
HeartBeat.StopSendingHeartBeat();
StopReceiving();
Instance?.Close();
foreach (Action<SocketObject> method in _boundEvents.ToList())
{
RemoveSocketObjectHandler(method);
}
Closed?.Invoke();
ConnectionLost = null;
Closed = null;
}
public void StartReceiving(Task t)
{
_receiving = true;
_receivingTask = t;
}
public void StopReceiving()
{
_receiving = false;
_receivingTask?.Wait(1);
_receivingTask = null;
}
}
}