Simulator/DroneSimulator/NetServerClients.cs
2025-04-06 17:17:15 +03:00

145 lines
3.5 KiB
C#

using System.Net.Sockets;
using System.Net;
using System.Drawing;
namespace DroneSimulator
{
internal class NetServerClients
{
public class ConnectData
{
public int ID;
public bool Connect;
public int Count;
public Socket? Client;
}
public class ReceiveData
{
public int ID;
public byte[]? Buffer;
public int Size;
public Socket? Client;
}
private class ClientData
{
public int ID;
public Socket? workSocket = null;
public byte[] buffer;
}
private int SocketID = 0;
private int SocketLimit;
private Socket? ServerSocket;
private List<ClientData> ClientSockets = new List<ClientData>();
public delegate int ServerCallback(object o);
private ServerCallback? ConnectionCallback;
private ServerCallback? ReceiveCallback;
private bool Active = false;
public enum ServerState { Error, Start, Stop };
public ServerState StartServer(int Port, int Limit, ServerCallback Connection, ServerCallback Receive)
{
if (Active)
{
ServerSocket?.Close();
foreach (ClientData c in ClientSockets)
{
try { c.workSocket?.Shutdown(SocketShutdown.Both); } catch { }
c.workSocket?.Close();
}
ClientSockets.Clear();
return ServerState.Stop;
}
ConnectionCallback = Connection;
ReceiveCallback = Receive;
SocketLimit = Limit;
IPEndPoint ip = new(IPAddress.Any, Port);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
ServerSocket.Bind(ip);
ServerSocket.Listen(10);
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
Active = true;
}
catch { ServerSocket.Close(); return ServerState.Error; }
return ServerState.Start;
}
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
if (listener == null) return;
Socket handler;
try { handler = listener.EndAccept(ar); }
catch{ ServerSocket?.Close(); Active = false; return; }
if (SocketLimit > ClientSockets.Count)
{
ClientData clientData = new ClientData();
clientData.ID = ++SocketID;
clientData.workSocket = handler;
ClientSockets.Add(clientData);
int size = ConnectionCallback(new ConnectData { ID = clientData.ID, Connect = true, Count = ClientSockets.Count, Client = handler });
clientData.buffer=new byte[size];
handler.BeginReceive(clientData.buffer, 0, size, 0, new AsyncCallback(ReadCallback), clientData);
}
else handler.Close();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
public void ReadCallback(IAsyncResult ar)
{
ClientData cd = (ClientData)ar.AsyncState;
if (cd == null) return;
int bytes = 0;
try { bytes = cd.workSocket.EndReceive(ar); }
catch { }
if (bytes == 0)
{
cd.workSocket?.Close();
ClientSockets.Remove(cd);
ConnectionCallback(new ConnectData { ID = cd.ID, Connect = false, Count = ClientSockets.Count, Client = null });
return;
}
int size = ReceiveCallback(new ReceiveData { ID = cd.ID, Buffer = cd.buffer, Size = bytes, Client = cd.workSocket });
cd.buffer = new byte[size];
try
{
cd.workSocket?.BeginReceive(cd.buffer, 0, size, 0, new AsyncCallback(ReadCallback), cd);
}
catch { }
}
}
}