Updated
This commit is contained in:
parent
604d9cbc6b
commit
04fd2329f1
|
@ -3,7 +3,6 @@
|
||||||
<LangVersion>Latest</LangVersion>
|
<LangVersion>Latest</LangVersion>
|
||||||
<TargetFrameworks>
|
<TargetFrameworks>
|
||||||
netstandard2.1;
|
netstandard2.1;
|
||||||
net5.0;
|
|
||||||
net6.0;
|
net6.0;
|
||||||
net7.0;
|
net7.0;
|
||||||
</TargetFrameworks>
|
</TargetFrameworks>
|
||||||
|
@ -17,9 +16,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.8</Version>
|
<Version>1.0.9</Version>
|
||||||
<AssemblyVersion>1.0.0.8</AssemblyVersion>
|
<AssemblyVersion>1.0.0.9</AssemblyVersion>
|
||||||
<FileVersion>1.0.0.8</FileVersion>
|
<FileVersion>1.0.0.9</FileVersion>
|
||||||
<PackageIcon>icon.png</PackageIcon>
|
<PackageIcon>icon.png</PackageIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,19 @@ namespace EonaCat.Network
|
||||||
internal static Logging Logger = new Logging();
|
internal static Logging Logger = new Logging();
|
||||||
private static QuicServer _quicServer;
|
private static QuicServer _quicServer;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnQuicClientConnected event
|
||||||
|
/// </summary>
|
||||||
public static event EventHandler<QuicConnectionEventArgs> OnQuicClientConnected;
|
public static event EventHandler<QuicConnectionEventArgs> OnQuicClientConnected;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnQuicStreamOpened event
|
||||||
|
/// </summary>
|
||||||
public static event EventHandler<QuicStreamEventArgs> OnQuicStreamOpened;
|
public static event EventHandler<QuicStreamEventArgs> OnQuicStreamOpened;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnQuicStreamDataReceived event
|
||||||
|
/// </summary>
|
||||||
public static event EventHandler<QuicStreamEventArgs> OnQuicStreamDataReceived;
|
public static event EventHandler<QuicStreamEventArgs> OnQuicStreamDataReceived;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -60,6 +69,13 @@ namespace EonaCat.Network
|
||||||
OnQuicStreamDataReceived?.Invoke(null, new QuicStreamEventArgs { Stream = stream, Data = data });
|
OnQuicStreamDataReceived?.Invoke(null, new QuicStreamEventArgs { Stream = stream, Data = data });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start a Quic client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ip"></param>
|
||||||
|
/// <param name="port"></param>
|
||||||
|
/// <param name="streamType"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public static QuicStream QuicStartClient(string ip, int port = 11000, StreamType streamType = StreamType.ClientBidirectional)
|
public static QuicStream QuicStartClient(string ip, int port = 11000, StreamType streamType = StreamType.ClientBidirectional)
|
||||||
{
|
{
|
||||||
QuicClient client = new QuicClient();
|
QuicClient client = new QuicClient();
|
||||||
|
|
|
@ -1,20 +1,45 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace EonaCat.Network
|
namespace EonaCat.Network
|
||||||
{
|
{
|
||||||
|
|
||||||
public class SocketTcpClient
|
public class SocketTcpClient
|
||||||
{
|
{
|
||||||
|
private const int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnConnect event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnConnect;
|
public event Action<RemoteInfo> OnConnect;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnReceive event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnReceive;
|
public event Action<RemoteInfo> OnReceive;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnDisconnect event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnDisconnect;
|
public event Action<RemoteInfo> OnDisconnect;
|
||||||
public event Action<RemoteInfo> OnSend;
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnError event
|
||||||
|
/// </summary>
|
||||||
public event Action<Exception, string> OnError;
|
public event Action<Exception, string> OnError;
|
||||||
|
|
||||||
private Socket socket;
|
private Socket socket;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create TCP client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <param name="port"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
public Task ConnectAsync(string ipAddress, int port)
|
public Task ConnectAsync(string ipAddress, int port)
|
||||||
{
|
{
|
||||||
if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
|
if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
|
||||||
|
@ -27,13 +52,13 @@ namespace EonaCat.Network
|
||||||
|
|
||||||
private async Task CreateSocketTcpClientAsync(IPAddress ipAddress, int port)
|
private async Task CreateSocketTcpClientAsync(IPAddress ipAddress, int port)
|
||||||
{
|
{
|
||||||
IsIP6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
|
IsIp6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
|
||||||
socket = new Socket(IsIP6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
socket = new Socket(IsIp6 ? AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await socket.ConnectAsync(ipAddress, port).ConfigureAwait(false);
|
await socket.ConnectAsync(ipAddress, port).ConfigureAwait(false);
|
||||||
OnConnect?.Invoke(new RemoteInfo { IsTcp = true, IsIpv6 = IsIP6 });
|
OnConnect?.Invoke(new RemoteInfo { IsTcp = true, IsIpv6 = IsIp6 });
|
||||||
await StartReceivingAsync();
|
_ = StartReceivingAsync();
|
||||||
}
|
}
|
||||||
catch (SocketException ex)
|
catch (SocketException ex)
|
||||||
{
|
{
|
||||||
|
@ -42,11 +67,11 @@ namespace EonaCat.Network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsIP6 { get; private set; }
|
public bool IsIp6 { get; set; }
|
||||||
|
|
||||||
private async Task StartReceivingAsync()
|
private async Task StartReceivingAsync()
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[1024];
|
byte[] buffer = new byte[BUFFER_SIZE]; // Increased buffer size for better performance
|
||||||
while (socket.Connected)
|
while (socket.Connected)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -54,13 +79,14 @@ namespace EonaCat.Network
|
||||||
int received = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None).ConfigureAwait(false);
|
int received = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), SocketFlags.None).ConfigureAwait(false);
|
||||||
if (received > 0)
|
if (received > 0)
|
||||||
{
|
{
|
||||||
byte[] data = buffer.AsSpan(0, received).ToArray();
|
byte[] data = new byte[received];
|
||||||
|
Buffer.BlockCopy(buffer, 0, data, 0, received);
|
||||||
OnReceive?.Invoke(new RemoteInfo
|
OnReceive?.Invoke(new RemoteInfo
|
||||||
{
|
{
|
||||||
IsTcp = true,
|
IsTcp = true,
|
||||||
Data = data,
|
Data = data,
|
||||||
EndPoint = socket.RemoteEndPoint,
|
EndPoint = socket.RemoteEndPoint,
|
||||||
IsIpv6 = IsIP6
|
IsIpv6 = socket.AddressFamily == AddressFamily.InterNetworkV6
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -74,15 +100,22 @@ namespace EonaCat.Network
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OnDisconnect?.Invoke(new RemoteInfo { IsTcp = true, EndPoint = socket.RemoteEndPoint, IsIpv6 = IsIP6 });
|
OnDisconnect?.Invoke(new RemoteInfo { IsTcp = true, EndPoint = socket.RemoteEndPoint, IsIpv6 = socket.AddressFamily == AddressFamily.InterNetworkV6 });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendAsync(byte[] data)
|
/// <summary>
|
||||||
|
/// Send data
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task SendAsync(byte[] data)
|
||||||
{
|
{
|
||||||
await socket.SendAsync(new ArraySegment<byte>(data), SocketFlags.None).ConfigureAwait(false);
|
return socket.SendAsync(new ArraySegment<byte>(data), SocketFlags.None);
|
||||||
OnSend?.Invoke(new RemoteInfo { EndPoint = socket.RemoteEndPoint, Data = data, IsIpv6 = IsIP6 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disconnect
|
||||||
|
/// </summary>
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
socket.Close();
|
socket.Close();
|
||||||
|
|
|
@ -8,41 +8,79 @@ namespace EonaCat.Network
|
||||||
{
|
{
|
||||||
public class SocketTcpServer
|
public class SocketTcpServer
|
||||||
{
|
{
|
||||||
|
private const int BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnConnect event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnConnect;
|
public event Action<RemoteInfo> OnConnect;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnReceive event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnReceive;
|
public event Action<RemoteInfo> OnReceive;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnSend event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnSend;
|
public event Action<RemoteInfo> OnSend;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnDisconnect event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnDisconnect;
|
public event Action<RemoteInfo> OnDisconnect;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnError event
|
||||||
|
/// </summary>
|
||||||
public event Action<Exception, string> OnError;
|
public event Action<Exception, string> OnError;
|
||||||
|
|
||||||
private TcpListener listener;
|
private readonly TcpListener _listener;
|
||||||
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
|
private Task _acceptTask;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create TCP server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <param name="port"></param>
|
||||||
public SocketTcpServer(IPAddress ipAddress, int port)
|
public SocketTcpServer(IPAddress ipAddress, int port)
|
||||||
{
|
{
|
||||||
listener = new TcpListener(ipAddress, port);
|
_listener = new TcpListener(ipAddress, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create TCP server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <param name="port"></param>
|
||||||
public SocketTcpServer(string ipAddress, int port)
|
public SocketTcpServer(string ipAddress, int port)
|
||||||
{
|
{
|
||||||
IPAddress address = IPAddress.Parse(ipAddress);
|
IPAddress address = IPAddress.Parse(ipAddress);
|
||||||
listener = new TcpListener(address, port);
|
_listener = new TcpListener(address, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task StartAsync(CancellationToken cancellationToken = default)
|
/// <summary>
|
||||||
|
/// Start TCP server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
_listener.Start();
|
||||||
|
_cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||||
|
_acceptTask = AcceptConnectionsAsync(_cancellationTokenSource.Token);
|
||||||
|
return _acceptTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task AcceptConnectionsAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
listener.Start();
|
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Socket socket = await listener.AcceptSocketAsync().ConfigureAwait(false);
|
var socket = await _listener.AcceptSocketAsync().ConfigureAwait(false);
|
||||||
OnConnect?.Invoke(new RemoteInfo
|
_ = HandleConnectionAsync(socket, cancellationToken);
|
||||||
{
|
|
||||||
Socket = socket,
|
|
||||||
IsTcp = true,
|
|
||||||
IsIpv6 = socket.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6,
|
|
||||||
EndPoint = socket.RemoteEndPoint
|
|
||||||
});
|
|
||||||
await StartReceivingAsync(socket, cancellationToken).ConfigureAwait(false);
|
|
||||||
}
|
}
|
||||||
catch (SocketException ex)
|
catch (SocketException ex)
|
||||||
{
|
{
|
||||||
|
@ -51,24 +89,33 @@ namespace EonaCat.Network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task StartReceivingAsync(Socket socket, CancellationToken cancellationToken)
|
private async Task HandleConnectionAsync(Socket socket, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
byte[] buffer = new byte[1024];
|
OnConnect?.Invoke(new RemoteInfo
|
||||||
|
{
|
||||||
|
Socket = socket,
|
||||||
|
IsTcp = true,
|
||||||
|
IsIpv6 = socket.AddressFamily == AddressFamily.InterNetworkV6,
|
||||||
|
EndPoint = socket.RemoteEndPoint
|
||||||
|
});
|
||||||
|
|
||||||
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int received = await socket.ReceiveAsync(new Memory<byte>(buffer), SocketFlags.None, cancellationToken)
|
int received = await socket.ReceiveAsync(new Memory<byte>(buffer), SocketFlags.None, cancellationToken).ConfigureAwait(false);
|
||||||
.ConfigureAwait(false);
|
|
||||||
if (received > 0)
|
if (received > 0)
|
||||||
{
|
{
|
||||||
|
byte[] data = new byte[received];
|
||||||
|
Buffer.BlockCopy(buffer, 0, data, 0, received);
|
||||||
OnReceive?.Invoke(new RemoteInfo
|
OnReceive?.Invoke(new RemoteInfo
|
||||||
{
|
{
|
||||||
Socket = socket,
|
Socket = socket,
|
||||||
IsTcp = true,
|
IsTcp = true,
|
||||||
IsIpv6 = socket.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6,
|
IsIpv6 = socket.AddressFamily == AddressFamily.InterNetworkV6,
|
||||||
EndPoint = socket.RemoteEndPoint,
|
EndPoint = socket.RemoteEndPoint,
|
||||||
Data = new Memory<byte>(buffer, 0, received).ToArray()
|
Data = data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -82,12 +129,51 @@ namespace EonaCat.Network
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnDisconnect?.Invoke(new RemoteInfo
|
||||||
|
{
|
||||||
|
Socket = socket,
|
||||||
|
IsTcp = true,
|
||||||
|
EndPoint = socket.RemoteEndPoint,
|
||||||
|
IsIpv6 = socket.AddressFamily == AddressFamily.InterNetworkV6
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SendTo(Socket socket, byte[] data)
|
/// <summary>
|
||||||
|
/// Send data to socket
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="socket"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task SendToAsync(Socket socket, byte[] data)
|
||||||
{
|
{
|
||||||
await socket.SendAsync(new ArraySegment<byte>(data), SocketFlags.None).ConfigureAwait(false);
|
await socket.SendAsync(new ArraySegment<byte>(data), SocketFlags.None).ConfigureAwait(false);
|
||||||
OnSend?.Invoke(new RemoteInfo { Socket = socket, IsTcp = true, EndPoint = socket.RemoteEndPoint, IsIpv6 = socket.RemoteEndPoint.AddressFamily == AddressFamily.InterNetworkV6, Data = data });
|
OnSend?.Invoke(new RemoteInfo
|
||||||
|
{
|
||||||
|
Socket = socket,
|
||||||
|
IsTcp = true,
|
||||||
|
EndPoint = socket.RemoteEndPoint,
|
||||||
|
IsIpv6 = socket.AddressFamily == AddressFamily.InterNetworkV6,
|
||||||
|
Data = data
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop TCP server
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public async Task StopAsync()
|
||||||
|
{
|
||||||
|
_cancellationTokenSource.Cancel();
|
||||||
|
_listener.Stop();
|
||||||
|
if (_acceptTask != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _acceptTask.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (AggregateException) { }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,14 +8,39 @@ namespace EonaCat.Network
|
||||||
{
|
{
|
||||||
public class SocketUdpClient
|
public class SocketUdpClient
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// OnConnect event
|
||||||
|
/// </summary>
|
||||||
public event Action<EndPoint> OnConnect;
|
public event Action<EndPoint> OnConnect;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnReceive event
|
||||||
|
/// </summary>
|
||||||
public event Action<byte[]> OnReceive;
|
public event Action<byte[]> OnReceive;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnDisconnect event
|
||||||
|
/// </summary>
|
||||||
public event Action<EndPoint> OnDisconnect;
|
public event Action<EndPoint> OnDisconnect;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnSend event
|
||||||
|
/// </summary>
|
||||||
public event Action<EndPoint, byte[]> OnSend;
|
public event Action<EndPoint, byte[]> OnSend;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnError event
|
||||||
|
/// </summary>
|
||||||
public event Action<Exception, string> OnError;
|
public event Action<Exception, string> OnError;
|
||||||
|
|
||||||
private UdpClient udpClient;
|
private UdpClient _udpClient;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create UDP client
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <param name="port"></param>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
public SocketUdpClient(IPAddress ipAddress, int port, CancellationToken cancellationToken = default)
|
public SocketUdpClient(IPAddress ipAddress, int port, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
CreateUdpClient(ipAddress, port, cancellationToken);
|
CreateUdpClient(ipAddress, port, cancellationToken);
|
||||||
|
@ -23,45 +48,36 @@ namespace EonaCat.Network
|
||||||
|
|
||||||
private void CreateUdpClient(IPAddress ipAddress, int port, CancellationToken cancellationToken = default)
|
private void CreateUdpClient(IPAddress ipAddress, int port, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
IsIP6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
|
IsIp6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
|
||||||
udpClient = new UdpClient(ipAddress.AddressFamily);
|
_udpClient = new UdpClient(ipAddress.AddressFamily);
|
||||||
|
|
||||||
if (IsIP6)
|
if (IsIp6)
|
||||||
{
|
{
|
||||||
udpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
|
_udpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
udpClient.Client.Bind(new IPEndPoint(IsIP6 ? IPAddress.IPv6Any : IPAddress.Any, 0));
|
_udpClient.Client.Bind(new IPEndPoint(IsIp6 ? IPAddress.IPv6Any : IPAddress.Any, 0));
|
||||||
|
|
||||||
if (IsMulticastGroupEnabled)
|
if (IsMulticastGroupEnabled)
|
||||||
{
|
{
|
||||||
udpClient.JoinMulticastGroup(ipAddress);
|
_udpClient.JoinMulticastGroup(ipAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnConnect?.Invoke(_udpClient.Client.RemoteEndPoint);
|
||||||
_ = StartReceivingAsync(cancellationToken);
|
_ = StartReceivingAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsMulticastGroupEnabled { get; set; }
|
public bool IsMulticastGroupEnabled { get; set; }
|
||||||
|
|
||||||
public bool IsIP6 { get; private set; }
|
public bool IsIp6 { get; private set; }
|
||||||
|
|
||||||
public SocketUdpClient(string ipAddress, int port)
|
private async Task StartReceivingAsync(CancellationToken cancellationToken)
|
||||||
{
|
|
||||||
if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
|
|
||||||
{
|
|
||||||
throw new Exception("Invalid ipAddress given");
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateUdpClient(ip, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task StartReceivingAsync(CancellationToken cancellationToken = default)
|
|
||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UdpReceiveResult result = await udpClient.ReceiveAsync().ConfigureAwait(false);
|
var result = await _udpClient.ReceiveAsync().ConfigureAwait(false);
|
||||||
OnReceive?.Invoke(result.Buffer);
|
OnReceive?.Invoke(result.Buffer);
|
||||||
}
|
}
|
||||||
catch (SocketException ex)
|
catch (SocketException ex)
|
||||||
|
@ -70,21 +86,30 @@ namespace EonaCat.Network
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OnDisconnect?.Invoke(udpClient.Client.RemoteEndPoint);
|
OnDisconnect?.Invoke(_udpClient.Client.RemoteEndPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send data to endPoint
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="endPoint"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task SendTo(EndPoint endPoint, byte[] data)
|
public async Task SendTo(EndPoint endPoint, byte[] data)
|
||||||
{
|
{
|
||||||
if (endPoint is IPEndPoint ipEndPoint)
|
if (endPoint is IPEndPoint ipEndPoint)
|
||||||
{
|
{
|
||||||
await udpClient.SendAsync(data, data.Length, ipEndPoint).ConfigureAwait(false);
|
await _udpClient.SendAsync(data, data.Length, ipEndPoint).ConfigureAwait(false);
|
||||||
OnSend?.Invoke(endPoint, data);
|
OnSend?.Invoke(endPoint, data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disconnect UDP client
|
||||||
|
/// </summary>
|
||||||
public void Disconnect()
|
public void Disconnect()
|
||||||
{
|
{
|
||||||
udpClient.Close();
|
_udpClient.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,21 +10,49 @@ namespace EonaCat.Network
|
||||||
{
|
{
|
||||||
public class SocketUdpServer
|
public class SocketUdpServer
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// OnReceive event
|
||||||
|
/// </summary>
|
||||||
public event Action<RemoteInfo> OnReceive;
|
public event Action<RemoteInfo> OnReceive;
|
||||||
public event Action<RemoteInfo> OnSend;
|
|
||||||
public event Action<Exception, string> OnError;
|
|
||||||
public event Action<RemoteInfo> OnDisconnect;
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnSend event
|
||||||
|
/// </summary>
|
||||||
|
public event Action<RemoteInfo> OnSend;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnError event
|
||||||
|
/// </summary>
|
||||||
|
public event Action<Exception, string> OnError;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// OnDisconnect event
|
||||||
|
/// </summary>
|
||||||
|
public event Action<RemoteInfo> OnDisconnect;
|
||||||
|
|
||||||
private UdpClient udpClient;
|
private UdpClient udpClient;
|
||||||
|
|
||||||
public bool IsIP6 { get; private set; }
|
/// <summary>
|
||||||
|
/// Determines if the UDP server is IpV6
|
||||||
|
/// </summary>
|
||||||
|
public bool IsIp6 { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create UDP server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <param name="port"></param>
|
||||||
public SocketUdpServer(IPAddress ipAddress, int port)
|
public SocketUdpServer(IPAddress ipAddress, int port)
|
||||||
{
|
{
|
||||||
CreateUdpServer(ipAddress, port);
|
CreateUdpServer(ipAddress, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create UDP server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="ipAddress"></param>
|
||||||
|
/// <param name="port"></param>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
public SocketUdpServer(string ipAddress, int port)
|
public SocketUdpServer(string ipAddress, int port)
|
||||||
{
|
{
|
||||||
if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
|
if (!IPAddress.TryParse(ipAddress, out IPAddress ip))
|
||||||
|
@ -35,7 +63,6 @@ namespace EonaCat.Network
|
||||||
CreateUdpServer(ip, port);
|
CreateUdpServer(ip, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static void SetConnectionReset(Socket socket)
|
private static void SetConnectionReset(Socket socket)
|
||||||
{
|
{
|
||||||
if (socket.ProtocolType != ProtocolType.Udp && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
if (socket.ProtocolType != ProtocolType.Udp && !RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
@ -52,11 +79,11 @@ namespace EonaCat.Network
|
||||||
|
|
||||||
private void CreateUdpServer(IPAddress ipAddress, int port)
|
private void CreateUdpServer(IPAddress ipAddress, int port)
|
||||||
{
|
{
|
||||||
IsIP6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
|
IsIp6 = ipAddress.AddressFamily == AddressFamily.InterNetworkV6;
|
||||||
udpClient = new UdpClient(ipAddress.AddressFamily);
|
udpClient = new UdpClient(ipAddress.AddressFamily);
|
||||||
SetConnectionReset(udpClient.Client);
|
SetConnectionReset(udpClient.Client);
|
||||||
|
|
||||||
if (IsIP6)
|
if (IsIp6)
|
||||||
{
|
{
|
||||||
udpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
|
udpClient.Client.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);
|
||||||
}
|
}
|
||||||
|
@ -64,13 +91,18 @@ namespace EonaCat.Network
|
||||||
udpClient.Client.Bind(new IPEndPoint(ipAddress, port));
|
udpClient.Client.Bind(new IPEndPoint(ipAddress, port));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start UDP server
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task StartAsync(CancellationToken cancellationToken = default)
|
public async Task StartAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
UdpReceiveResult result = await udpClient.ReceiveAsync().ConfigureAwait(false);
|
var result = await udpClient.ReceiveAsync().ConfigureAwait(false);
|
||||||
OnReceive?.Invoke(new RemoteInfo()
|
OnReceive?.Invoke(new RemoteInfo()
|
||||||
{
|
{
|
||||||
EndPoint = result.RemoteEndPoint,
|
EndPoint = result.RemoteEndPoint,
|
||||||
|
@ -85,6 +117,12 @@ namespace EonaCat.Network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send data to endPoint
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="endPoint"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task SendToAsync(EndPoint endPoint, byte[] data)
|
public async Task SendToAsync(EndPoint endPoint, byte[] data)
|
||||||
{
|
{
|
||||||
if (endPoint is IPEndPoint ipEndPoint)
|
if (endPoint is IPEndPoint ipEndPoint)
|
||||||
|
@ -94,15 +132,21 @@ namespace EonaCat.Network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Send data to all clients
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
public async Task SendToAllAsync(byte[] data)
|
public async Task SendToAllAsync(byte[] data)
|
||||||
{
|
{
|
||||||
// get all connected clients
|
// get all connected clients
|
||||||
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
|
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
|
||||||
IPEndPoint[] endPoints = ipProperties.GetActiveUdpListeners();
|
var endPoints = ipProperties.GetActiveUdpListeners();
|
||||||
foreach (IPEndPoint endPoint in endPoints)
|
foreach (var endPoint in endPoints)
|
||||||
{
|
{
|
||||||
await udpClient.SendAsync(data, data.Length, endPoint).ConfigureAwait(false);
|
await udpClient.SendAsync(data, data.Length, endPoint).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue