Updated
This commit is contained in:
parent
a5e2cbaf57
commit
ff98074f5b
|
@ -18,9 +18,9 @@
|
||||||
<PackageTags>EonaCat, Network, .NET Standard, EonaCatHelpers, Jeroen, Saey, Protocol, Quic, UDP, TCP, Web, Server</PackageTags>
|
<PackageTags>EonaCat, Network, .NET Standard, EonaCatHelpers, Jeroen, Saey, Protocol, Quic, UDP, TCP, Web, Server</PackageTags>
|
||||||
<PackageReleaseNotes></PackageReleaseNotes>
|
<PackageReleaseNotes></PackageReleaseNotes>
|
||||||
<Description>EonaCat Networking library with Quic, TCP, UDP and a Webserver</Description>
|
<Description>EonaCat Networking library with Quic, TCP, UDP and a Webserver</Description>
|
||||||
<Version>1.0.2</Version>
|
<Version>1.0.3</Version>
|
||||||
<AssemblyVersion>1.0.0.2</AssemblyVersion>
|
<AssemblyVersion>1.0.0.3</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.2</FileVersion>
|
<FileVersion>1.0.0.3</FileVersion>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="EonaCat.Controls" Version="1.0.2" />
|
||||||
<PackageReference Include="EonaCat.Json" Version="1.0.3" />
|
<PackageReference Include="EonaCat.Json" Version="1.0.3" />
|
||||||
<PackageReference Include="EonaCat.LogSystem" Version="1.0.0" />
|
<PackageReference Include="EonaCat.LogSystem" Version="1.0.0" />
|
||||||
<PackageReference Include="EonaCat.Matchers" Version="1.0.0" />
|
<PackageReference Include="EonaCat.Matchers" Version="1.0.0" />
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
public delegate void SendBytesTo(byte[] data, EndPoint point);
|
public delegate void SendBytesTo(byte[] data, EndPoint point);
|
||||||
|
|
||||||
public class ClientConnection : IDisposable
|
public class Client : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Unique client id.
|
/// Unique client id.
|
||||||
|
@ -43,10 +43,7 @@ namespace EonaCat.Sockets
|
||||||
|
|
||||||
public event SendBytesTo SendData;
|
public event SendBytesTo SendData;
|
||||||
|
|
||||||
/// <summary>
|
public Client()
|
||||||
/// ClientConnection class constructor.
|
|
||||||
/// </summary>
|
|
||||||
public ClientConnection()
|
|
||||||
{
|
{
|
||||||
Buffer = new byte[BufferSize];
|
Buffer = new byte[BufferSize];
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ using System.Net.Sockets;
|
||||||
|
|
||||||
namespace EonaCat.Sockets
|
namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
public class SocketClient : ClientConnection, IDisposable
|
public class SocketClient : Client, IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Client type
|
/// Client type
|
||||||
|
|
|
@ -5,7 +5,8 @@ using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading;
|
using System.Threading.Tasks;
|
||||||
|
using EonaCat.Helpers.Controls;
|
||||||
|
|
||||||
namespace EonaCat.Sockets
|
namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
|
@ -29,7 +30,7 @@ namespace EonaCat.Sockets
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// List of connected clients.
|
/// List of connected clients.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<ClientConnection> ConnectedClients { get; set; } = new List<ClientConnection>();
|
public List<Client> ConnectedClients { get; set; } = new List<Client>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interval to check for disconnected clients
|
/// Interval to check for disconnected clients
|
||||||
|
@ -44,9 +45,8 @@ namespace EonaCat.Sockets
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if the socket is in blocking mode
|
/// Determines if the socket is in blocking mode
|
||||||
/// (default: true)
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool IsSocketInBlockingMode { get; set; } = true;
|
public bool IsSocketBlockingDisabled { get; set; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -60,9 +60,9 @@ namespace EonaCat.Sockets
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Only for UDP.
|
/// Only for UDP.
|
||||||
/// Required to use SocketClient class for this.
|
/// (default: true)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UDPClientManage { get; set; } = true;
|
public bool UseClientManager { get; set; } = true;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Only for UDP.
|
/// Only for UDP.
|
||||||
|
@ -96,18 +96,20 @@ namespace EonaCat.Sockets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler OnStop;
|
public event EventHandler OnStop;
|
||||||
|
|
||||||
private Socket Listener { get; set; }
|
private Socket Server { get; set; }
|
||||||
private System.Timers.Timer DisconnectTimer { get; set; }
|
private EonaCatTimer DisconnectTimerUdp { get; set; }
|
||||||
|
private EonaCatTimer DisconnectTimerTcp { get; set; }
|
||||||
private Dictionary<EndPoint, double> LastDataReceivedTime { get; set; }
|
private Dictionary<EndPoint, double> LastDataReceivedTime { get; set; }
|
||||||
private double TimeNow { get => (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; }
|
private double TimeNow { get => (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; }
|
||||||
|
|
||||||
public SocketServer(NetworkType type, string address, int port)
|
public SocketServer(NetworkType type, string address, int port)
|
||||||
{
|
{
|
||||||
if (IPAddress.TryParse(address, out var ipAddress))
|
if (!IPAddress.TryParse(address, out var ipAddress))
|
||||||
{
|
{
|
||||||
new SocketServer(type, ipAddress, port);
|
throw new Exception("Invalid IP address specified");
|
||||||
}
|
}
|
||||||
throw new Exception("Invalid IP address specified");
|
|
||||||
|
SetupSocketServer(type, ipAddress, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -117,12 +119,63 @@ namespace EonaCat.Sockets
|
||||||
/// <param name="address">Server listening ip</param>
|
/// <param name="address">Server listening ip</param>
|
||||||
/// <param name="port">Server listening port</param>
|
/// <param name="port">Server listening port</param>
|
||||||
public SocketServer(NetworkType type, IPAddress address, int port)
|
public SocketServer(NetworkType type, IPAddress address, int port)
|
||||||
|
{
|
||||||
|
SetupSocketServer(type, address, port);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupSocketServer(NetworkType type, IPAddress address, int port)
|
||||||
{
|
{
|
||||||
Guid = System.Guid.NewGuid().ToString();
|
Guid = System.Guid.NewGuid().ToString();
|
||||||
ServerType = type;
|
ServerType = type;
|
||||||
IPAddress = address;
|
IPAddress = address;
|
||||||
Port = port;
|
Port = port;
|
||||||
DisconnectTimer = new System.Timers.Timer(DisconnectionCheckInterval);
|
}
|
||||||
|
|
||||||
|
private readonly List<EndPoint> _removedEndpoints = new List<EndPoint>();
|
||||||
|
|
||||||
|
private void UdpCheckCallback()
|
||||||
|
{
|
||||||
|
_removedEndpoints.Clear();
|
||||||
|
var now = TimeNow;
|
||||||
|
foreach (var kp in LastDataReceivedTime.Where(kp => now - kp.Value > _UDPDataInterval / 1000))
|
||||||
|
{
|
||||||
|
lock (ConnectedClients)
|
||||||
|
{
|
||||||
|
var client = ConnectedClients.FirstOrDefault(x => x.Guid == kp.Key.ToString());
|
||||||
|
if (client == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
||||||
|
ConnectedClients.Remove(client);
|
||||||
|
_removedEndpoints.Add(kp.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lock (LastDataReceivedTime)
|
||||||
|
{
|
||||||
|
foreach (var r in _removedEndpoints)
|
||||||
|
{
|
||||||
|
LastDataReceivedTime.Remove(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TcpCheckCallback()
|
||||||
|
{
|
||||||
|
lock (ConnectedClients)
|
||||||
|
{
|
||||||
|
ConnectedClients.RemoveAll(x =>
|
||||||
|
{
|
||||||
|
if (x.IsConnected)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = x });
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
@ -133,96 +186,52 @@ namespace EonaCat.Sockets
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start server
|
/// Start server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Start()
|
public async Task StartAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (ServerType)
|
switch (ServerType)
|
||||||
{
|
{
|
||||||
case NetworkType.Tcp:
|
case NetworkType.Tcp:
|
||||||
Listener = new Socket(IPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
Server = new Socket(IPAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
|
||||||
ConfigureSocketOptions();
|
ConfigureSocketOptions();
|
||||||
|
|
||||||
// Check if we need to override the socket with a custom socket
|
// Check if we need to override the socket with a custom socket
|
||||||
if (CustomTcpSocket != null)
|
if (CustomTcpSocket != null)
|
||||||
{
|
{
|
||||||
Listener = CustomTcpSocket;
|
Server = CustomTcpSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
DisconnectTimer.Elapsed += (s, e) =>
|
DisconnectTimerTcp = new EonaCatTimer(TimeSpan.FromMilliseconds(DisconnectionCheckInterval), TcpCheckCallback);
|
||||||
{
|
DisconnectTimerTcp.Start();
|
||||||
lock (ConnectedClients)
|
|
||||||
{
|
|
||||||
ConnectedClients.RemoveAll(x =>
|
|
||||||
{
|
|
||||||
if (x.IsConnected)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = x });
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
break;
|
break;
|
||||||
case NetworkType.Udp:
|
case NetworkType.Udp:
|
||||||
{
|
{
|
||||||
if (UDPClientManage)
|
if (UseClientManager)
|
||||||
{
|
{
|
||||||
LastDataReceivedTime = new Dictionary<EndPoint, double>();
|
LastDataReceivedTime = new Dictionary<EndPoint, double>();
|
||||||
DisconnectTimer.Elapsed += (s, e) =>
|
DisconnectTimerUdp = new EonaCatTimer(TimeSpan.FromMilliseconds(DisconnectionCheckInterval), UdpCheckCallback);
|
||||||
{
|
DisconnectTimerUdp.Start();
|
||||||
var now = TimeNow;
|
|
||||||
var times = LastDataReceivedTime;
|
|
||||||
var removed = new List<EndPoint>();
|
|
||||||
foreach (var kp in times)
|
|
||||||
{
|
|
||||||
if (now - kp.Value > _UDPDataInterval / 1000)
|
|
||||||
{
|
|
||||||
lock (ConnectedClients)
|
|
||||||
{
|
|
||||||
var client = ConnectedClients.Where(x => x.Guid == kp.Key.ToString());
|
|
||||||
if (!client.Any())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client.First() });
|
|
||||||
ConnectedClients.Remove(client.First());
|
|
||||||
removed.Add(kp.Key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lock (LastDataReceivedTime)
|
|
||||||
{
|
|
||||||
foreach (var r in removed)
|
|
||||||
{
|
|
||||||
LastDataReceivedTime.Remove(r);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
Listener = new Socket(IPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
Server = new Socket(IPAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
||||||
ConfigureSocketOptions();
|
ConfigureSocketOptions();
|
||||||
|
|
||||||
// Check if we need to override the socket with a custom socket
|
// Check if we need to override the socket with a custom socket
|
||||||
if (CustomUdpSocket != null)
|
if (CustomUdpSocket != null)
|
||||||
{
|
{
|
||||||
Listener = CustomUdpSocket;
|
Server = CustomUdpSocket;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Listener.ReceiveBufferSize = ClientConnection.BufferSize;
|
Server.ReceiveBufferSize = Client.BufferSize;
|
||||||
Listener.SendBufferSize = ClientConnection.BufferSize;
|
Server.SendBufferSize = Client.BufferSize;
|
||||||
Listener.Bind(new IPEndPoint(IPAddress, Port));
|
Server.Bind(new IPEndPoint(IPAddress, Port));
|
||||||
if (ServerType == NetworkType.Tcp)
|
if (ServerType == NetworkType.Tcp)
|
||||||
{
|
{
|
||||||
Listener.Listen(Backlog);
|
Server.Listen(Backlog);
|
||||||
}
|
}
|
||||||
DisconnectTimer.Start();
|
await Task.Run(ListenLoop);
|
||||||
ListenerLoop();
|
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
@ -261,14 +270,14 @@ namespace EonaCat.Sockets
|
||||||
private void ConfigureSocketOptions()
|
private void ConfigureSocketOptions()
|
||||||
{
|
{
|
||||||
// Disable ICMP packet shutdown
|
// Disable ICMP packet shutdown
|
||||||
SetConnectionReset(Listener);
|
SetConnectionReset(Server);
|
||||||
|
|
||||||
if (ReuseAddress)
|
if (ReuseAddress)
|
||||||
{
|
{
|
||||||
Listener.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Listener.Blocking = IsSocketInBlockingMode;
|
Server.Blocking = IsSocketBlockingDisabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -278,7 +287,8 @@ namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
DisconnectTimer.Stop();
|
DisconnectTimerUdp?.Stop();
|
||||||
|
DisconnectTimerTcp?.Stop();
|
||||||
foreach (var client in ConnectedClients)
|
foreach (var client in ConnectedClients)
|
||||||
{
|
{
|
||||||
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
||||||
|
@ -286,7 +296,7 @@ namespace EonaCat.Sockets
|
||||||
}
|
}
|
||||||
ConnectedClients.Clear();
|
ConnectedClients.Clear();
|
||||||
OnStop?.Invoke(this, EventArgs.Empty);
|
OnStop?.Invoke(this, EventArgs.Empty);
|
||||||
Listener.Close();
|
Server.Close();
|
||||||
}
|
}
|
||||||
catch (SocketException socketException)
|
catch (SocketException socketException)
|
||||||
{
|
{
|
||||||
|
@ -294,35 +304,29 @@ namespace EonaCat.Sockets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ListenerLoop()
|
private void ListenLoop()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
OnStart?.Invoke(this, CustomTcpSocket != null || CustomUdpSocket != null ? "Custom socket was used" : string.Empty);
|
OnStart?.Invoke(this, CustomTcpSocket != null || CustomUdpSocket != null ? "Custom socket was used" : string.Empty);
|
||||||
if (ServerType == NetworkType.Tcp)
|
|
||||||
{
|
|
||||||
Listener.BeginAccept(AcceptCallback, Listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ServerType != NetworkType.Udp)
|
switch (ServerType)
|
||||||
{
|
{
|
||||||
return;
|
case NetworkType.Tcp:
|
||||||
}
|
Server.BeginAccept(AcceptCallback, Server);
|
||||||
var loopbackAddress = Listener.AddressFamily == AddressFamily.InterNetworkV6
|
break;
|
||||||
? IPAddress.IPv6Loopback
|
|
||||||
: IPAddress.Loopback;
|
|
||||||
|
|
||||||
if (UDPClientManage)
|
case NetworkType.Udp:
|
||||||
{
|
var loopbackAddress = Server.AddressFamily == AddressFamily.InterNetworkV6
|
||||||
var buffer = new byte[ClientConnection.BufferSize];
|
? IPAddress.IPv6Loopback
|
||||||
EndPoint remoteIp = new IPEndPoint(loopbackAddress, 0);
|
: IPAddress.Loopback;
|
||||||
Listener.BeginReceiveFrom(buffer, 0, ClientConnection.BufferSize, 0, ref remoteIp, AcceptCallbackUDP, new object[] { buffer, remoteIp, Listener });
|
|
||||||
}
|
var buffer = new byte[Client.BufferSize];
|
||||||
else
|
EndPoint remoteIp = new IPEndPoint(loopbackAddress, 0);
|
||||||
{
|
Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, UseClientManager ? AcceptClientsCallbackUDP : ReadClientCallbackUdp, new object[] { buffer, remoteIp, Server });
|
||||||
var buffer = new byte[ClientConnection.BufferSize];
|
break;
|
||||||
EndPoint remoteEp = new IPEndPoint(loopbackAddress, 0);
|
default:
|
||||||
Listener.BeginReceiveFrom(buffer, 0, ClientConnection.BufferSize, 0, ref remoteEp, ReadCallbackUDP, new object[] { buffer, remoteEp, Listener });
|
throw new NotSupportedException("Protocol type not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
|
@ -337,7 +341,7 @@ namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
var listener = (Socket)ar.AsyncState;
|
var listener = (Socket)ar.AsyncState;
|
||||||
var handler = listener.EndAccept(ar);
|
var handler = listener.EndAccept(ar);
|
||||||
var client = new ClientConnection()
|
var client = new Client()
|
||||||
{
|
{
|
||||||
Guid = System.Guid.NewGuid().ToString(),
|
Guid = System.Guid.NewGuid().ToString(),
|
||||||
Socket = handler
|
Socket = handler
|
||||||
|
@ -347,8 +351,8 @@ namespace EonaCat.Sockets
|
||||||
ConnectedClients.Add(client);
|
ConnectedClients.Add(client);
|
||||||
}
|
}
|
||||||
OnConnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
OnConnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
||||||
client.Socket.BeginReceive(client.Buffer, 0, ClientConnection.BufferSize, 0, ReadCallback, client);
|
client.Socket.BeginReceive(client.Buffer, 0, Client.BufferSize, 0, ReadCallback, client);
|
||||||
listener.BeginAccept(AcceptCallback, Listener);
|
listener.BeginAccept(AcceptCallback, Server);
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
@ -361,7 +365,7 @@ namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = (ClientConnection)ar.AsyncState;
|
var client = (Client)ar.AsyncState;
|
||||||
var bytesRead = client.Socket.EndReceive(ar);
|
var bytesRead = client.Socket.EndReceive(ar);
|
||||||
if (bytesRead > 0)
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
|
@ -369,8 +373,7 @@ namespace EonaCat.Sockets
|
||||||
Array.Copy(client.Buffer, 0, data, 0, bytesRead);
|
Array.Copy(client.Buffer, 0, data, 0, bytesRead);
|
||||||
OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data });
|
OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data });
|
||||||
}
|
}
|
||||||
Thread.Sleep(DisconnectionCheckInterval);
|
client.Socket.BeginReceive(client.Buffer, 0, Client.BufferSize, 0, ReadCallback, client);
|
||||||
client.Socket.BeginReceive(client.Buffer, 0, ClientConnection.BufferSize, 0, ReadCallback, client);
|
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
@ -379,7 +382,7 @@ namespace EonaCat.Sockets
|
||||||
catch (ObjectDisposedException) { }
|
catch (ObjectDisposedException) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AcceptCallbackUDP(IAsyncResult ar)
|
private void AcceptClientsCallbackUDP(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -388,27 +391,28 @@ namespace EonaCat.Sockets
|
||||||
var remoteIp = objects[1] as EndPoint;
|
var remoteIp = objects[1] as EndPoint;
|
||||||
var listener = objects[2] as Socket;
|
var listener = objects[2] as Socket;
|
||||||
var bytesRead = listener.EndReceiveFrom(ar, ref remoteIp);
|
var bytesRead = listener.EndReceiveFrom(ar, ref remoteIp);
|
||||||
var clients = ConnectedClients.Where(x => x.Guid == remoteIp.ToString()).ToList();
|
|
||||||
ClientConnection client;
|
Client client;
|
||||||
if (clients.Count == 0)
|
lock (ConnectedClients)
|
||||||
{
|
{
|
||||||
client = new ClientConnection()
|
client = ConnectedClients.FirstOrDefault(x => x.Guid == remoteIp.ToString());
|
||||||
|
if (client == null)
|
||||||
{
|
{
|
||||||
Guid = remoteIp.ToString(),
|
client = new Client()
|
||||||
Socket = new Socket(remoteIp.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
|
{
|
||||||
};
|
Guid = remoteIp.ToString(),
|
||||||
client.SendData += SendData;
|
Socket = new Socket(remoteIp.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
|
||||||
client.Socket.Connect(remoteIp);
|
};
|
||||||
if (client.IsConnected)
|
client.SendData += SendData;
|
||||||
{
|
client.Socket.Connect(remoteIp);
|
||||||
ConnectedClients.Add(client);
|
if (client.IsConnected)
|
||||||
OnConnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
{
|
||||||
|
ConnectedClients.Add(client);
|
||||||
|
OnConnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
client = clients.First();
|
|
||||||
}
|
|
||||||
if (bytesRead > 1)
|
if (bytesRead > 1)
|
||||||
{
|
{
|
||||||
var data = new byte[bytesRead];
|
var data = new byte[bytesRead];
|
||||||
|
@ -417,16 +421,20 @@ namespace EonaCat.Sockets
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (LastDataReceivedTime.ContainsKey(remoteIp))
|
lock (LastDataReceivedTime)
|
||||||
{
|
{
|
||||||
LastDataReceivedTime[remoteIp] = TimeNow;
|
if (LastDataReceivedTime.ContainsKey(remoteIp))
|
||||||
}
|
{
|
||||||
else
|
LastDataReceivedTime[remoteIp] = TimeNow;
|
||||||
{
|
}
|
||||||
LastDataReceivedTime.Add(remoteIp, TimeNow);
|
else
|
||||||
|
{
|
||||||
|
LastDataReceivedTime.Add(remoteIp, TimeNow);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Listener.BeginReceiveFrom(buffer, 0, ClientConnection.BufferSize, 0, ref remoteIp, AcceptCallbackUDP, new object[] { buffer, remoteIp, Listener });
|
|
||||||
|
Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, AcceptClientsCallbackUDP, new object[] { buffer, remoteIp, listener });
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
@ -435,22 +443,30 @@ namespace EonaCat.Sockets
|
||||||
catch (ObjectDisposedException) { }
|
catch (ObjectDisposedException) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReadCallbackUDP(IAsyncResult ar)
|
private void ReadClientCallbackUdp(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var objects = (object[])ar.AsyncState;
|
var objects = (object[])ar.AsyncState;
|
||||||
var buffer = objects[0] as byte[];
|
var buffer = objects[0] as byte[];
|
||||||
var remote_ip = objects[1] as EndPoint;
|
var remoteIp = objects[1] as EndPoint;
|
||||||
var listener = objects[2] as Socket;
|
var listener = objects[2] as Socket;
|
||||||
var bytesRead = listener.EndReceiveFrom(ar, ref remote_ip);
|
var bytesRead = listener.EndReceiveFrom(ar, ref remoteIp);
|
||||||
if (bytesRead > 0)
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
var data = new byte[bytesRead];
|
var data = new byte[bytesRead];
|
||||||
Array.Copy(buffer, 0, data, 0, bytesRead);
|
Array.Copy(buffer, 0, data, 0, bytesRead);
|
||||||
OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Data = data });
|
OnReceived?.Invoke(this, new SocketServerDataEventArgs()
|
||||||
|
{
|
||||||
|
Data = data,
|
||||||
|
Client = new Client()
|
||||||
|
{
|
||||||
|
Guid = remoteIp.ToString(),
|
||||||
|
Socket = new Socket(remoteIp.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Listener.BeginReceiveFrom(buffer, 0, ClientConnection.BufferSize, 0, ref remote_ip, ReadCallbackUDP, new object[] { buffer, remote_ip, Listener });
|
Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, ReadClientCallbackUdp, new object[] { buffer, remoteIp, Server });
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
@ -463,7 +479,7 @@ namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var client = (ClientConnection)ar.AsyncState;
|
var client = (Client)ar.AsyncState;
|
||||||
client.Socket.EndDisconnect(ar);
|
client.Socket.EndDisconnect(ar);
|
||||||
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
||||||
lock (ConnectedClients)
|
lock (ConnectedClients)
|
||||||
|
@ -481,7 +497,7 @@ namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Listener.BeginSendTo(data, 0, data.Length, 0, point, EndSendTo, null);
|
Server.BeginSendTo(data, 0, data.Length, 0, point, EndSendTo, null);
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
@ -493,7 +509,7 @@ namespace EonaCat.Sockets
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Listener.EndSendTo(ar);
|
Server.EndSendTo(ar);
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,11 +5,12 @@ namespace EonaCat.Sockets
|
||||||
public class SocketServerDataEventArgs : EventArgs
|
public class SocketServerDataEventArgs : EventArgs
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Client connection.
|
/// Client.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ClientConnection Client { get; set; }
|
public Client Client { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recieved data.
|
/// Received data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[] Data { get; set; }
|
public byte[] Data { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -19,6 +20,6 @@ namespace EonaCat.Sockets
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Client connection.
|
/// Client connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ClientConnection Client { get; set; }
|
public Client Client { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net;
|
|
||||||
|
|
||||||
namespace EonaCat.Sockets
|
|
||||||
{
|
|
||||||
public class SocketServerPool : IDisposable
|
|
||||||
{
|
|
||||||
public List<SocketServer> Servers { get; set; } = new List<SocketServer>();
|
|
||||||
|
|
||||||
public SocketServer this[int index]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Servers.Count < index)
|
|
||||||
return Servers[index];
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public SocketServer this[string name]
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
var server = Servers.Where(x => x.Guid == name);
|
|
||||||
if (server.Count() > 0)
|
|
||||||
return server.First();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Servers.ForEach(x => x.Stop());
|
|
||||||
Servers.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SocketServer Add(NetworkType type, IPAddress ip, int port)
|
|
||||||
{
|
|
||||||
SocketServer server = new SocketServer(type, ip, port);
|
|
||||||
Servers.Add(server);
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(string name)
|
|
||||||
{
|
|
||||||
int count = Servers.RemoveAll(x => x.Guid == name);
|
|
||||||
return count > 0 ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Remove(int index)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Servers.RemoveAt(index);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue