This commit is contained in:
EonaCat 2023-03-24 14:05:23 +01:00
parent ff98074f5b
commit fb824136d9
3 changed files with 90 additions and 68 deletions

View File

@ -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>

View File

@ -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.

View File

@ -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