Files
linker/linker.messenger/MessengerServer.cs
snltty 03145bb6d0 sync
2024-10-20 23:26:57 +08:00

129 lines
3.9 KiB
C#

using linker.libs.extends;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System;
using linker.messenger.resolver;
using System.Threading;
namespace linker.plugins.server
{
public sealed class MessengerServer
{
private Socket socket;
private Socket socketUdp;
private CancellationTokenSource cancellationTokenSource;
private readonly ResolverTransfer resolverTransfer;
public MessengerServer(ResolverTransfer resolverTransfer)
{
this.resolverTransfer = resolverTransfer;
cancellationTokenSource = new CancellationTokenSource();
}
public void Start(int port)
{
if (socket == null)
{
socket = BindAccept(port);
}
}
private async Task BindUdp(int port)
{
socketUdp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socketUdp.Bind(new IPEndPoint(IPAddress.Any, port));
socketUdp.WindowsUdpBug();
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, IPEndPoint.MinPort);
byte[] buffer = new byte[1 * 1024 * 1024];
while (true)
{
try
{
SocketReceiveFromResult result = await socketUdp.ReceiveFromAsync(buffer, SocketFlags.None, endPoint).ConfigureAwait(false);
IPEndPoint ep = result.RemoteEndPoint as IPEndPoint;
try
{
await resolverTransfer.BeginReceive(socketUdp, ep, buffer.AsMemory(0, result.ReceivedBytes)).ConfigureAwait(false);
}
catch (Exception)
{
}
}
catch (Exception)
{
break;
}
}
}
private Socket BindAccept(int port)
{
IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, port);
Socket socket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.IPv6Only(localEndPoint.AddressFamily, false);
socket.ReuseBind(localEndPoint);
socket.Listen(int.MaxValue);
SocketAsyncEventArgs acceptEventArg = new SocketAsyncEventArgs
{
UserToken = socket,
SocketFlags = SocketFlags.None,
};
acceptEventArg.Completed += IO_Completed;
StartAccept(acceptEventArg);
_ = BindUdp(port);
return socket;
}
private void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
acceptEventArg.AcceptSocket = null;
Socket token = (Socket)acceptEventArg.UserToken;
try
{
if (token.AcceptAsync(acceptEventArg) == false)
{
ProcessAccept(acceptEventArg);
}
}
catch (Exception)
{
token?.SafeClose();
}
}
private void IO_Completed(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Accept:
ProcessAccept(e);
break;
default:
break;
}
}
private void ProcessAccept(SocketAsyncEventArgs e)
{
if (e.AcceptSocket != null)
{
_ = resolverTransfer.BeginReceive(e.AcceptSocket);
StartAccept(e);
}
}
public void Stop()
{
cancellationTokenSource?.Cancel();
socket?.SafeClose();
socket = null;
}
public void Disponse()
{
Stop();
}
}
}