Updated
This commit is contained in:
parent
ff98074f5b
commit
fb824136d9
|
@ -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.3</Version>
|
<Version>1.0.5</Version>
|
||||||
<AssemblyVersion>1.0.0.3</AssemblyVersion>
|
<AssemblyVersion>1.0.0.5</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.3</FileVersion>
|
<FileVersion>1.0.0.5</FileVersion>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace EonaCat.Sockets
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Buffer size
|
/// Buffer size
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static int BufferSize { get; set; } = 8 * 1024; // 8KB
|
public static int BufferSize { get; set; } = 1024 * 1024; // 1024KB
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Socket connection state.
|
/// Socket connection state.
|
||||||
|
|
|
@ -5,6 +5,7 @@ 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 System.Threading.Tasks;
|
||||||
using EonaCat.Helpers.Controls;
|
using EonaCat.Helpers.Controls;
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ namespace EonaCat.Sockets
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interval to check for disconnected clients
|
/// Interval to check for disconnected clients
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int DisconnectionCheckInterval { get; set; } = 100;
|
public int DisconnectionCheckInterval { get; set; } = 50;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines if we need to reuse the socket address
|
/// Determines if we need to reuse the socket address
|
||||||
|
@ -251,20 +252,18 @@ namespace EonaCat.Sockets
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Socket CustomTcpSocket { get; set; }
|
public Socket CustomTcpSocket { get; set; }
|
||||||
|
|
||||||
static void SetConnectionReset(Socket socket)
|
private static void SetConnectionReset(Socket socket)
|
||||||
{
|
{
|
||||||
try
|
if (socket.ProtocolType != ProtocolType.Udp || !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
{
|
{
|
||||||
if (socket.ProtocolType == ProtocolType.Udp && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
return;
|
||||||
{
|
|
||||||
// Disable ICMP packet shutdown (forcibly closed)
|
|
||||||
const uint IOC_IN = 0x80000000;
|
|
||||||
const uint IOC_VENDOR = 0x18000000;
|
|
||||||
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
|
||||||
socket.IOControl((int)SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
catch { }
|
|
||||||
|
// Disable ICMP packet shutdown (forcibly closed)
|
||||||
|
const uint IOC_IN = 0x80000000;
|
||||||
|
const uint IOC_VENDOR = 0x18000000;
|
||||||
|
uint SIO_UDP_CONNRESET = IOC_IN | IOC_VENDOR | 12;
|
||||||
|
socket.IOControl((int)SIO_UDP_CONNRESET, new[] { Convert.ToByte(false) }, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConfigureSocketOptions()
|
private void ConfigureSocketOptions()
|
||||||
|
@ -313,18 +312,13 @@ namespace EonaCat.Sockets
|
||||||
switch (ServerType)
|
switch (ServerType)
|
||||||
{
|
{
|
||||||
case NetworkType.Tcp:
|
case NetworkType.Tcp:
|
||||||
Server.BeginAccept(AcceptCallback, Server);
|
BeginTcpAccept();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NetworkType.Udp:
|
case NetworkType.Udp:
|
||||||
var loopbackAddress = Server.AddressFamily == AddressFamily.InterNetworkV6
|
BeginUdpReceive();
|
||||||
? IPAddress.IPv6Loopback
|
|
||||||
: IPAddress.Loopback;
|
|
||||||
|
|
||||||
var buffer = new byte[Client.BufferSize];
|
|
||||||
EndPoint remoteIp = new IPEndPoint(loopbackAddress, 0);
|
|
||||||
Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, UseClientManager ? AcceptClientsCallbackUDP : ReadClientCallbackUdp, new object[] { buffer, remoteIp, Server });
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException("Protocol type not supported");
|
throw new NotSupportedException("Protocol type not supported");
|
||||||
}
|
}
|
||||||
|
@ -335,6 +329,61 @@ namespace EonaCat.Sockets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void BeginTcpAccept()
|
||||||
|
{
|
||||||
|
Server.BeginAccept(AcceptCallback, Server);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginUdpReceive()
|
||||||
|
{
|
||||||
|
var loopbackAddress = Server.AddressFamily == AddressFamily.InterNetworkV6
|
||||||
|
? IPAddress.IPv6Loopback
|
||||||
|
: IPAddress.Loopback;
|
||||||
|
|
||||||
|
var buffer = new byte[Client.BufferSize];
|
||||||
|
EndPoint remoteIp = new IPEndPoint(loopbackAddress, 0);
|
||||||
|
Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, UseClientManager ? AcceptClientsCallbackUdp : ReadClientCallbackUdp, new object[] { buffer, remoteIp, Server });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReadCallback(IAsyncResult ar)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var client = (Client)ar.AsyncState;
|
||||||
|
var bytesRead = client.Socket.EndReceive(ar);
|
||||||
|
if (bytesRead > 0)
|
||||||
|
{
|
||||||
|
var data = new byte[bytesRead];
|
||||||
|
Array.Copy(client.Buffer, 0, data, 0, bytesRead);
|
||||||
|
OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data });
|
||||||
|
|
||||||
|
// read any remaining data
|
||||||
|
while (client.Socket.Available > 0)
|
||||||
|
{
|
||||||
|
bytesRead = client.Socket.Receive(client.Buffer, 0, Client.BufferSize, SocketFlags.None);
|
||||||
|
data = new byte[bytesRead];
|
||||||
|
Array.Copy(client.Buffer, 0, data, 0, bytesRead);
|
||||||
|
OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data });
|
||||||
|
}
|
||||||
|
|
||||||
|
client.Socket.BeginReceive(client.Buffer, 0, Client.BufferSize, 0, ReadCallback, client); // recursive call
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
||||||
|
lock (ConnectedClients)
|
||||||
|
{
|
||||||
|
ConnectedClients.Remove(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (SocketException se)
|
||||||
|
{
|
||||||
|
OnError?.Invoke(this, new ErrorEventArgs(se));
|
||||||
|
}
|
||||||
|
catch (ObjectDisposedException) { }
|
||||||
|
}
|
||||||
|
|
||||||
private void AcceptCallback(IAsyncResult ar)
|
private void AcceptCallback(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -350,39 +399,27 @@ 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, Client.BufferSize, 0, ReadCallback, client);
|
client.Socket.BeginReceive(client.Buffer, 0, Client.BufferSize, 0, ReadCallback, client); // recursive call
|
||||||
listener.BeginAccept(AcceptCallback, Server);
|
|
||||||
}
|
|
||||||
catch (SocketException se)
|
|
||||||
{
|
|
||||||
OnError?.Invoke(this, new ErrorEventArgs(se));
|
|
||||||
}
|
|
||||||
catch (ObjectDisposedException) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ReadCallback(IAsyncResult ar)
|
Thread.Sleep(DisconnectionCheckInterval);
|
||||||
{
|
|
||||||
try
|
if (listener.IsBound) // check if the listener is still bound
|
||||||
{
|
|
||||||
var client = (Client)ar.AsyncState;
|
|
||||||
var bytesRead = client.Socket.EndReceive(ar);
|
|
||||||
if (bytesRead > 0)
|
|
||||||
{
|
{
|
||||||
var data = new byte[bytesRead];
|
listener.BeginAccept(AcceptCallback, Server); // recursive call
|
||||||
Array.Copy(client.Buffer, 0, data, 0, bytesRead);
|
|
||||||
OnReceived?.Invoke(this, new SocketServerDataEventArgs() { Client = client, Data = data });
|
|
||||||
}
|
}
|
||||||
client.Socket.BeginReceive(client.Buffer, 0, Client.BufferSize, 0, ReadCallback, client);
|
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
OnError?.Invoke(this, new ErrorEventArgs(se));
|
OnError?.Invoke(this, new ErrorEventArgs(se));
|
||||||
}
|
}
|
||||||
catch (ObjectDisposedException) { }
|
catch (ObjectDisposedException)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AcceptClientsCallbackUDP(IAsyncResult ar)
|
private void AcceptClientsCallbackUdp(IAsyncResult ar)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -413,7 +450,7 @@ namespace EonaCat.Sockets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytesRead > 1)
|
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);
|
||||||
|
@ -434,7 +471,7 @@ namespace EonaCat.Sockets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, AcceptClientsCallbackUDP, 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)
|
||||||
{
|
{
|
||||||
|
@ -452,7 +489,7 @@ 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);
|
||||||
if (bytesRead > 0)
|
while (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);
|
||||||
|
@ -465,8 +502,11 @@ namespace EonaCat.Sockets
|
||||||
Socket = new Socket(remoteIp.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
|
Socket = new Socket(remoteIp.AddressFamily, SocketType.Dgram, ProtocolType.Udp)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// read any remaining data
|
||||||
|
bytesRead = listener.ReceiveFrom(buffer, 0, Client.BufferSize, SocketFlags.None, ref remoteIp);
|
||||||
}
|
}
|
||||||
Server.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, ReadClientCallbackUdp, new object[] { buffer, remoteIp, Server });
|
listener.BeginReceiveFrom(buffer, 0, Client.BufferSize, 0, ref remoteIp, ReadClientCallbackUdp, new object[] { buffer, remoteIp, listener });
|
||||||
}
|
}
|
||||||
catch (SocketException se)
|
catch (SocketException se)
|
||||||
{
|
{
|
||||||
|
@ -475,24 +515,6 @@ namespace EonaCat.Sockets
|
||||||
catch (ObjectDisposedException) { }
|
catch (ObjectDisposedException) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
private void DisconnectCallback(IAsyncResult ar)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var client = (Client)ar.AsyncState;
|
|
||||||
client.Socket.EndDisconnect(ar);
|
|
||||||
OnDisconnected?.Invoke(this, new SocketServerClientEventArgs() { Client = client });
|
|
||||||
lock (ConnectedClients)
|
|
||||||
{
|
|
||||||
ConnectedClients.Remove(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (SocketException se)
|
|
||||||
{
|
|
||||||
OnError?.Invoke(this, new ErrorEventArgs(se));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SendData(byte[] data, EndPoint point)
|
public void SendData(byte[] data, EndPoint point)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
Loading…
Reference in New Issue