commit efce29d97388bd19c651aab3996475308ccfa0ee
parent cbc87b28ece603083065b5cb2b481f5d0d0f4eba
Author: Mikolaj Lenczewski <33129490+EnderRifter@users.noreply.github.com>
Date: Fri, 21 Feb 2020 19:05:38 +0000
Now we have a performance problem. Good job me...
Diffstat:
14 files changed, 688 insertions(+), 690 deletions(-)
diff --git a/NetSharp/NetSharp/Client.cs b/NetSharp/NetSharp/Client.cs
@@ -1,6 +1,7 @@
using System;
using System.Net;
using System.Net.Sockets;
+using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
@@ -17,9 +18,23 @@ namespace NetSharp
public abstract class Client : Connection, IClient, IDisposable
{
/// <summary>
- /// Provides <see cref="CancellationToken"/> instances for cancelling methods after a timeout period.
+ /// Initialises a new instance of the <see cref="Client"/> class.
+ /// </summary>
+ private Client()
+ {
+ remoteEndPoint = new IPEndPoint(IPAddress.None, IPEndPoint.MinPort);
+ socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+
+ socketOptions = new DefaultSocketOptions(ref socket);
+ }
+
+ /// <summary>
+ /// Destroys an instance of the <see cref="Client"/> class.
/// </summary>
- protected readonly CancellationTokenSource cancellationTokenSource;
+ ~Client()
+ {
+ Dispose(false);
+ }
/// <summary>
/// The <see cref="Socket"/> underlying the connection.
@@ -39,19 +54,6 @@ namespace NetSharp
/// <summary>
/// Initialises a new instance of the <see cref="Client"/> class.
/// </summary>
- private Client()
- {
- cancellationTokenSource = new CancellationTokenSource();
-
- remoteEndPoint = new IPEndPoint(IPAddress.None, IPEndPoint.MinPort);
- socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
-
- socketOptions = new DefaultSocketOptions(ref socket);
- }
-
- /// <summary>
- /// Initialises a new instance of the <see cref="Client"/> class.
- /// </summary>
/// <param name="socketType">The socket type for the underlying socket.</param>
/// <param name="protocolType">The protocol type for the underlying socket.</param>
/// <param name="socketManager">The <see cref="Utils.Socket_Options.SocketOptions"/> manager to use.</param>
@@ -68,28 +70,6 @@ namespace NetSharp
}
/// <summary>
- /// Destroys an instance of the <see cref="Client"/> class.
- /// </summary>
- ~Client()
- {
- Dispose(false);
- }
-
- /// <inheritdoc />
- public event Action<EndPoint>? Connected;
-
- /// <inheritdoc />
- public event Action<EndPoint>? Disconnected;
-
- /// <summary>
- /// The configured socket options for the underlying connection.
- /// </summary>
- public SocketOptions SocketOptions
- {
- get { return socketOptions; }
- }
-
- /// <summary>
/// Disposes of this <see cref="Client"/> instance.
/// </summary>
/// <param name="disposing">Whether this instance is being disposed.</param>
@@ -97,8 +77,7 @@ namespace NetSharp
{
if (disposing)
{
- cancellationTokenSource?.Dispose();
- socket?.Dispose();
+ socket.Dispose();
}
base.Dispose(disposing);
@@ -118,6 +97,20 @@ namespace NetSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected void OnDisconnected(EndPoint endPoint) => Disconnected?.Invoke(endPoint);
+ /// <inheritdoc />
+ public event Action<EndPoint>? Connected;
+
+ /// <inheritdoc />
+ public event Action<EndPoint>? Disconnected;
+
+ /// <summary>
+ /// The configured socket options for the underlying connection.
+ /// </summary>
+ public SocketOptions SocketOptions
+ {
+ get { return socketOptions; }
+ }
+
/// <summary>
/// Disconnects the client from the remote endpoint.
/// </summary>
@@ -149,41 +142,43 @@ namespace NetSharp
public abstract Task<bool> SendSimpleAsync<Req>(Req request, TimeSpan timeout) where Req : IRequestPacket, new();
/// <inheritdoc />
- public async Task<bool> TryBindAsync(IPAddress? localAddress, int? localPort, TimeSpan timeout)
+ public Task<bool> TryBindAsync(IPAddress? localAddress, int? localPort, TimeSpan timeout)
{
+ CancellationTokenSource cts = new CancellationTokenSource(timeout);
EndPoint localEndPoint = new IPEndPoint(localAddress ?? IPAddress.Any, localPort ?? 0);
try
{
- cancellationTokenSource.CancelAfter(timeout);
-
- return await Task.Run(() =>
+ return Task.Run(() =>
{
socket.Bind(localEndPoint);
return true;
- }, cancellationTokenSource.Token);
+ }, cts.Token);
}
catch (TaskCanceledException)
{
- return false;
+ return Task.FromResult(false);
}
catch (SocketException ex)
{
logger.LogException($"Socket exception on binding socket to {localEndPoint}:", ex);
- return false;
+ return Task.FromResult(false);
+ }
+ finally
+ {
+ cts.Dispose();
}
}
/// <inheritdoc />
public async Task<bool> TryConnectAsync(IPAddress remoteAddress, int remotePort, TimeSpan timeout)
{
+ CancellationTokenSource cts = new CancellationTokenSource(timeout);
remoteEndPoint = new IPEndPoint(remoteAddress, remotePort);
try
{
- cancellationTokenSource.CancelAfter(timeout);
-
return await Task.Run(async () =>
{
await socket.ConnectAsync(remoteEndPoint);
@@ -194,7 +189,7 @@ namespace NetSharp
OnConnected(SocketOptions.RemoteIPEndPoint);
return true;
- }, cancellationTokenSource.Token);
+ }, cts.Token);
}
catch (TaskCanceledException)
{
@@ -205,6 +200,10 @@ namespace NetSharp
logger.LogException($"Socket exception on connection to {remoteEndPoint}:", ex);
return false;
}
+ finally
+ {
+ cts.Dispose();
+ }
}
}
}
\ No newline at end of file
diff --git a/NetSharp/NetSharp/Clients/TcpClient.cs b/NetSharp/NetSharp/Clients/TcpClient.cs
@@ -1,5 +1,6 @@
using System;
using System.Net.Sockets;
+using System.Threading;
using System.Threading.Tasks;
using NetSharp.Packets;
using NetSharp.Packets.Builtin;
diff --git a/NetSharp/NetSharp/Clients/UdpClient.cs b/NetSharp/NetSharp/Clients/UdpClient.cs
@@ -1,5 +1,6 @@
using System;
using System.Net.Sockets;
+using System.Threading;
using System.Threading.Tasks;
using NetSharp.Packets;
using NetSharp.Packets.Builtin;
diff --git a/NetSharp/NetSharp/Connection.cs b/NetSharp/NetSharp/Connection.cs
@@ -41,16 +41,6 @@ namespace NetSharp
}
/// <summary>
- /// Signifies that some data has been received from the remote endpoint.
- /// </summary>
- public event Action<EndPoint, int>? BytesReceived;
-
- /// <summary>
- /// Signifies that some data was sent to the remote endpoint.
- /// </summary>
- public event Action<EndPoint, int>? BytesSent;
-
- /// <summary>
/// Disposes of this <see cref="Connection"/> instance.
/// </summary>
/// <param name="disposing">Whether this instance is being disposed.</param>
@@ -63,194 +53,189 @@ namespace NetSharp
}
/// <summary>
- /// Listens for a packet to be received asynchronously within the given timeout, and returns the received packet.
+ /// Listens for a packet to be received from the network.
/// </summary>
/// <param name="remoteSocket">The remote socket from which to receive data.</param>
/// <param name="socketFlags">The socket flags associated with the read operation.</param>
/// <param name="timeout">
- /// The timespan within which to wait for a packet, returning a null packet if this limit is exceeded.
+ /// The timespan within which the packet should be received. After this timespan elapses, the receive task is cancelled.
/// </param>
+ /// <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
/// <returns>The packet that was received. <see cref="NullPacket"/> if not received correctly.</returns>
- protected async Task<Packet> DoReceivePacketAsync(Socket remoteSocket, SocketFlags socketFlags, TimeSpan timeout)
+ protected Task<Packet> DoReceivePacketAsync(Socket remoteSocket, SocketFlags socketFlags, TimeSpan timeout,
+ CancellationToken cancellationToken = default)
{
- CancellationTokenSource cts = new CancellationTokenSource(timeout);
+ CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout);
+ CancellationTokenSource cts =
+ CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, cancellationToken);
try
{
- Packet request =
- await NetworkOperations.ReadPacketAsync(remoteSocket, socketFlags, cts.Token);
+ return Task.Factory.StartNew(() =>
+ {
+ Packet request = NetworkOperations.ReadPacket(remoteSocket, socketFlags);
- OnBytesReceived(remoteSocket.RemoteEndPoint, request.TotalSize);
+ OnBytesReceived(remoteSocket.RemoteEndPoint, request.TotalSize);
- return request;
- }
- catch (OperationCanceledException ex)
- {
- logger.LogException(
- $"Could not receive a packet from {remoteSocket.RemoteEndPoint} within the given timeout ({timeout}):",
- ex);
- return NullPacket;
+ return request;
+ }, cts.Token);
}
catch (SocketException ex)
{
logger.LogException($"Socket exception while reading bytes from {remoteSocket.RemoteEndPoint}:", ex);
- return NullPacket;
+ return Task.FromResult(NullPacket);
}
catch (Exception ex)
{
logger.LogException($"Exception while reading bytes from {remoteSocket.RemoteEndPoint}:", ex);
- return NullPacket;
+ return Task.FromResult(NullPacket);
}
finally
{
cts.Dispose();
+ timeoutCancellationTokenSource.Dispose();
}
}
/// <summary>
- /// Listens for a packet to be received asynchronously within the given timeout, and returns the received packet.
+ /// Listens for a packet to be received from the network.
/// </summary>
/// <param name="socket">The socket which will receive the packet.</param>
/// <param name="remoteEndPoint">The remote endpoint from which to receive the packet.</param>
/// <param name="socketFlags">The socket flags associated with the read operation.</param>
/// <param name="timeout">
- /// The timespan within which to wait for a packet, returning a null packet if this limit is exceeded.
+ /// The timespan within which the packet should be received. After this timespan elapses, the receive task is cancelled.
/// </param>
+ /// <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
/// <returns>
/// The packet that was received and the associated transmission result. <see cref="NullPacket"/> if not received correctly.
/// </returns>
- protected async Task<(Packet request, TransmissionResult packetResult)> DoReceivePacketFromAsync(
- Socket socket, EndPoint remoteEndPoint, SocketFlags socketFlags, TimeSpan timeout)
+ protected Task<(Packet request, TransmissionResult packetResult)> DoReceivePacketFromAsync(Socket socket,
+ EndPoint remoteEndPoint, SocketFlags socketFlags, TimeSpan timeout, CancellationToken cancellationToken = default)
{
- CancellationTokenSource cts = new CancellationTokenSource(timeout);
+ CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout);
+ CancellationTokenSource cts =
+ CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, cancellationToken);
try
{
- (Packet request, TransmissionResult packetResult) result =
- await NetworkOperations.ReadPacketFromAsync(socket, remoteEndPoint, socketFlags, cts.Token);
+ return Task.Factory.StartNew(() =>
+ {
+ (Packet request, TransmissionResult packetResult) result =
+ NetworkOperations.ReadPacketFrom(socket, remoteEndPoint, socketFlags);
- OnBytesReceived(remoteEndPoint, result.request.TotalSize);
+ OnBytesReceived(result.packetResult.RemoteEndPoint, result.request.TotalSize);
- return result;
- }
- catch (OperationCanceledException ex)
- {
- logger.LogException(
- $"Could not receive a packet from {remoteEndPoint} within the given timeout ({timeout}):", ex);
- return (NullPacket, NullTransmissionResult);
+ return result;
+ }, cts.Token);
}
catch (SocketException ex)
{
logger.LogException($"Socket exception while reading bytes from {remoteEndPoint}:", ex);
- return (NullPacket, NullTransmissionResult);
+ return Task.FromResult((NullPacket, NullTransmissionResult));
}
catch (Exception ex)
{
logger.LogException($"Exception while reading bytes from {remoteEndPoint}:", ex);
- return (NullPacket, NullTransmissionResult);
+ return Task.FromResult((NullPacket, NullTransmissionResult));
}
finally
{
cts.Dispose();
+ timeoutCancellationTokenSource.Dispose();
}
}
/// <summary>
- /// Sends the given packet asynchronously within the given timeout.
+ /// Sends the given packet to the network.
/// </summary>
/// <param name="remoteSocket">The remote socket to which to send the packet.</param>
/// <param name="packet">The packet to send.</param>
/// <param name="socketFlags">The socket flags associated with the write operation.</param>
/// <param name="timeout">
- /// The timespan within which to send the packet, returning <c>false</c> if this limit is exceeded.
+ /// The timespan within which the packet should be received. After this timespan elapses, the send task is cancelled.
/// </param>
+ /// <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
/// <returns>Whether the packet was successfully sent.</returns>
- protected async Task<bool> DoSendPacketAsync(Socket remoteSocket, Packet packet, SocketFlags socketFlags, TimeSpan timeout)
+ protected Task<bool> DoSendPacketAsync(Socket remoteSocket, Packet packet, SocketFlags socketFlags, TimeSpan timeout,
+ CancellationToken cancellationToken = default)
{
- CancellationTokenSource cts = new CancellationTokenSource(timeout);
+ CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout);
+ CancellationTokenSource cts =
+ CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, cancellationToken);
try
{
- await NetworkOperations.WritePacketAsync(remoteSocket, packet, socketFlags, cts.Token);
+ return Task.Factory.StartNew(() =>
+ {
+ NetworkOperations.WritePacket(remoteSocket, packet, socketFlags);
- OnBytesSent(remoteSocket.RemoteEndPoint, packet.TotalSize);
+ OnBytesSent(remoteSocket.RemoteEndPoint, packet.TotalSize);
- return true;
- }
- catch (OperationCanceledException ex)
- {
- logger.LogException(
- $"Could not send the packet to {remoteSocket.RemoteEndPoint} within the given timeout ({timeout}):",
- ex);
- return false;
+ return true;
+ }, cts.Token);
}
catch (SocketException ex)
{
logger.LogException($"Socket exception while sending bytes to {remoteSocket.RemoteEndPoint}:", ex);
- return false;
+ return Task.FromResult(false);
}
catch (Exception ex)
{
logger.LogException($"Exception while sending bytes to {remoteSocket.RemoteEndPoint}:", ex);
- return false;
+ return Task.FromResult(false);
}
finally
{
cts.Dispose();
+ timeoutCancellationTokenSource.Dispose();
}
}
/// <summary>
- /// Sends the given packet asynchronously within the given timeout.
+ /// Sends the given packet to the network.
/// </summary>
/// <param name="socket">The socket which should send the packet.</param>
/// <param name="remoteEndPoint">The remote endpoint to which to send the packet.</param>
/// <param name="packet">The packet to send.</param>
/// <param name="socketFlags">The socket flags associated with the write operation.</param>
/// <param name="timeout">
- /// The timespan within which to send the packet, returning <c>false</c> if this limit is exceeded.
+ /// The timespan within which the packet should be received. After this timespan elapses, the send task is cancelled.
/// </param>
+ /// <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
/// <returns>Whether the packet was successfully sent.</returns>
- protected async Task<bool> DoSendPacketToAsync(Socket socket, EndPoint remoteEndPoint, Packet packet,
- SocketFlags socketFlags, TimeSpan timeout)
+ protected Task<bool> DoSendPacketToAsync(Socket socket, EndPoint remoteEndPoint, Packet packet, SocketFlags socketFlags,
+ TimeSpan timeout, CancellationToken cancellationToken = default)
{
- CancellationTokenSource cts = new CancellationTokenSource(timeout);
+ CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout);
+ CancellationTokenSource cts =
+ CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, cancellationToken);
try
{
- if (packet.TotalSize > Constants.UdpMaxBufferSize)
+ return Task.Factory.StartNew(() =>
{
- throw new Exception(
- $"The given UDP packet exceeded the maximum allowed size of {Constants.UdpMaxBufferSize}, " +
- "and could not be sent. Consider splitting up the packet into multiple, smaller packets " +
- "that are less likely to get lost due to fragmentation, or using TCP instead.");
- }
+ NetworkOperations.WritePacketTo(socket, remoteEndPoint, packet, socketFlags);
- await NetworkOperations.WritePacketToAsync(socket, remoteEndPoint, packet, socketFlags, cts.Token);
+ OnBytesSent(remoteEndPoint, packet.TotalSize);
- OnBytesSent(remoteEndPoint, packet.TotalSize);
-
- return true;
- }
- catch (OperationCanceledException ex)
- {
- logger.LogException(
- $"Could not send the packet to {remoteEndPoint} within the given timeout ({timeout}):", ex);
- return false;
+ return true;
+ }, cts.Token);
}
catch (SocketException ex)
{
logger.LogException($"Socket exception while sending bytes to {remoteEndPoint}:", ex);
- return false;
+ return Task.FromResult(false);
}
catch (Exception ex)
{
logger.LogException($"Exception while sending bytes to {remoteEndPoint}:", ex);
- return false;
+ return Task.FromResult(false);
}
finally
{
cts.Dispose();
+ timeoutCancellationTokenSource.Dispose();
}
}
@@ -273,6 +258,16 @@ namespace NetSharp
BytesSent?.Invoke(remoteEndPoint, bytesSent);
/// <summary>
+ /// Signifies that some data has been received from the remote endpoint.
+ /// </summary>
+ public event Action<EndPoint, int>? BytesReceived;
+
+ /// <summary>
+ /// Signifies that some data was sent to the remote endpoint.
+ /// </summary>
+ public event Action<EndPoint, int>? BytesSent;
+
+ /// <summary>
/// Makes the client log to the given stream.
/// </summary>
/// <param name="loggingStream">The stream that new messages should be logged to.</param>
@@ -281,9 +276,7 @@ namespace NetSharp
/// </param>
public void ChangeLoggingStream(Stream loggingStream, LogLevel minimumMessageSeverityLevel = LogLevel.Info)
{
- logger = new Logger(loggingStream);
-
- logger.SetMinimumLogSeverity(minimumMessageSeverityLevel);
+ logger = new Logger(loggingStream, minimumMessageSeverityLevel);
}
/// <inheritdoc />
diff --git a/NetSharp/NetSharp/Logging/Logger.cs b/NetSharp/NetSharp/Logging/Logger.cs
@@ -34,7 +34,7 @@ namespace NetSharp.Logging
/// <summary>
/// A simple logger capable of writing text to a stream.
/// </summary>
- public struct Logger : IDisposable
+ public readonly struct Logger : IDisposable
{
/// <summary>
/// The stream to which messages will be logged.
@@ -42,25 +42,26 @@ namespace NetSharp.Logging
private readonly Stream loggingStream;
/// <summary>
- /// The text writer we will use to log messages to the underlying stream.
+ /// The minimum severity that log messages need to be logged to the underlying stream.
/// </summary>
- private readonly StreamWriter writer;
+ private readonly LogLevel minimumSeverity;
/// <summary>
- /// The minimum severity that log messages need to be logged to the underlying stream.
+ /// The text writer we will use to log messages to the underlying stream.
/// </summary>
- private LogLevel minimumSeverity;
+ private readonly StreamWriter writer;
/// <summary>
/// Initialises a new instance of the <see cref="Logger"/> struct.
/// </summary>
- /// <param name="streamToLogTo">The stream that the logger instance should log messages to.</param>
- public Logger(Stream streamToLogTo)
+ /// <param name="outputStream">The stream that the logger instance should log messages to.</param>
+ /// <param name="minimumLogSeverity">The minimum log level that will be logged to the output stream.</param>
+ public Logger(Stream outputStream, LogLevel minimumLogSeverity = LogLevel.Info)
{
- loggingStream = streamToLogTo;
+ loggingStream = outputStream;
writer = new StreamWriter(loggingStream, Encoding.Default) { AutoFlush = true };
- minimumSeverity = LogLevel.Info;
+ minimumSeverity = minimumLogSeverity;
}
/// <inheritdoc />
@@ -189,11 +190,5 @@ namespace NetSharp.Logging
/// </summary>
/// <param name="message">The warning that should be logged.</param>
public async Task LogWarningAsync(string message) => await LogAsync(message, null, LogLevel.Warn);
-
- /// <summary>
- /// Sets the minimum severity level that new messages need to be logged to the underlying stream.
- /// </summary>
- /// <param name="minimumSeverityLevel">The new minimum severity level.</param>
- public void SetMinimumLogSeverity(LogLevel minimumSeverityLevel) => minimumSeverity = minimumSeverityLevel;
}
}
\ No newline at end of file
diff --git a/NetSharp/NetSharp/NetSharp.xml b/NetSharp/NetSharp/NetSharp.xml
@@ -9,9 +9,14 @@
Provides methods for connecting to and talking with a <see cref="T:NetSharp.Interfaces.IServer"/> instance.
</summary>
</member>
- <member name="F:NetSharp.Client.cancellationTokenSource">
+ <member name="M:NetSharp.Client.#ctor">
<summary>
- Provides <see cref="T:System.Threading.CancellationToken"/> instances for cancelling methods after a timeout period.
+ Initialises a new instance of the <see cref="T:NetSharp.Client"/> class.
+ </summary>
+ </member>
+ <member name="M:NetSharp.Client.Finalize">
+ <summary>
+ Destroys an instance of the <see cref="T:NetSharp.Client"/> class.
</summary>
</member>
<member name="F:NetSharp.Client.socket">
@@ -29,11 +34,6 @@
The remote endpoint with which this client communicates.
</summary>
</member>
- <member name="M:NetSharp.Client.#ctor">
- <summary>
- Initialises a new instance of the <see cref="T:NetSharp.Client"/> class.
- </summary>
- </member>
<member name="M:NetSharp.Client.#ctor(System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,NetSharp.Utils.Socket_Options.SocketOptionManager)">
<summary>
Initialises a new instance of the <see cref="T:NetSharp.Client"/> class.
@@ -42,22 +42,6 @@
<param name="protocolType">The protocol type for the underlying socket.</param>
<param name="socketManager">The <see cref="T:NetSharp.Utils.Socket_Options.SocketOptions"/> manager to use.</param>
</member>
- <member name="M:NetSharp.Client.Finalize">
- <summary>
- Destroys an instance of the <see cref="T:NetSharp.Client"/> class.
- </summary>
- </member>
- <member name="E:NetSharp.Client.Connected">
- <inheritdoc />
- </member>
- <member name="E:NetSharp.Client.Disconnected">
- <inheritdoc />
- </member>
- <member name="P:NetSharp.Client.SocketOptions">
- <summary>
- The configured socket options for the underlying connection.
- </summary>
- </member>
<member name="M:NetSharp.Client.Dispose(System.Boolean)">
<summary>
Disposes of this <see cref="T:NetSharp.Client"/> instance.
@@ -76,6 +60,17 @@
</summary>
<param name="endPoint">The remote endpoint with which a connection was lost.</param>
</member>
+ <member name="E:NetSharp.Client.Connected">
+ <inheritdoc />
+ </member>
+ <member name="E:NetSharp.Client.Disconnected">
+ <inheritdoc />
+ </member>
+ <member name="P:NetSharp.Client.SocketOptions">
+ <summary>
+ The configured socket options for the underlying connection.
+ </summary>
+ </member>
<member name="M:NetSharp.Client.Disconnect">
<summary>
Disconnects the client from the remote endpoint.
@@ -164,70 +159,64 @@
Initialises a new instance of the <see cref="T:NetSharp.Connection"/> class.
</summary>
</member>
- <member name="E:NetSharp.Connection.BytesReceived">
- <summary>
- Signifies that some data has been received from the remote endpoint.
- </summary>
- </member>
- <member name="E:NetSharp.Connection.BytesSent">
- <summary>
- Signifies that some data was sent to the remote endpoint.
- </summary>
- </member>
<member name="M:NetSharp.Connection.Dispose(System.Boolean)">
<summary>
Disposes of this <see cref="T:NetSharp.Connection"/> instance.
</summary>
<param name="disposing">Whether this instance is being disposed.</param>
</member>
- <member name="M:NetSharp.Connection.DoReceivePacketAsync(System.Net.Sockets.Socket,System.Net.Sockets.SocketFlags,System.TimeSpan)">
+ <member name="M:NetSharp.Connection.DoReceivePacketAsync(System.Net.Sockets.Socket,System.Net.Sockets.SocketFlags,System.TimeSpan,System.Threading.CancellationToken)">
<summary>
- Listens for a packet to be received asynchronously within the given timeout, and returns the received packet.
+ Listens for a packet to be received from the network.
</summary>
<param name="remoteSocket">The remote socket from which to receive data.</param>
<param name="socketFlags">The socket flags associated with the read operation.</param>
<param name="timeout">
- The timespan within which to wait for a packet, returning a null packet if this limit is exceeded.
+ The timespan within which the packet should be received. After this timespan elapses, the receive task is cancelled.
</param>
+ <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
<returns>The packet that was received. <see cref="F:NetSharp.Connection.NullPacket"/> if not received correctly.</returns>
</member>
- <member name="M:NetSharp.Connection.DoReceivePacketFromAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.TimeSpan)">
+ <member name="M:NetSharp.Connection.DoReceivePacketFromAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.TimeSpan,System.Threading.CancellationToken)">
<summary>
- Listens for a packet to be received asynchronously within the given timeout, and returns the received packet.
+ Listens for a packet to be received from the network.
</summary>
<param name="socket">The socket which will receive the packet.</param>
<param name="remoteEndPoint">The remote endpoint from which to receive the packet.</param>
<param name="socketFlags">The socket flags associated with the read operation.</param>
<param name="timeout">
- The timespan within which to wait for a packet, returning a null packet if this limit is exceeded.
+ The timespan within which the packet should be received. After this timespan elapses, the receive task is cancelled.
</param>
+ <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
<returns>
The packet that was received and the associated transmission result. <see cref="F:NetSharp.Connection.NullPacket"/> if not received correctly.
</returns>
</member>
- <member name="M:NetSharp.Connection.DoSendPacketAsync(System.Net.Sockets.Socket,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags,System.TimeSpan)">
+ <member name="M:NetSharp.Connection.DoSendPacketAsync(System.Net.Sockets.Socket,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags,System.TimeSpan,System.Threading.CancellationToken)">
<summary>
- Sends the given packet asynchronously within the given timeout.
+ Sends the given packet to the network.
</summary>
<param name="remoteSocket">The remote socket to which to send the packet.</param>
<param name="packet">The packet to send.</param>
<param name="socketFlags">The socket flags associated with the write operation.</param>
<param name="timeout">
- The timespan within which to send the packet, returning <c>false</c> if this limit is exceeded.
+ The timespan within which the packet should be received. After this timespan elapses, the send task is cancelled.
</param>
+ <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
<returns>Whether the packet was successfully sent.</returns>
</member>
- <member name="M:NetSharp.Connection.DoSendPacketToAsync(System.Net.Sockets.Socket,System.Net.EndPoint,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags,System.TimeSpan)">
+ <member name="M:NetSharp.Connection.DoSendPacketToAsync(System.Net.Sockets.Socket,System.Net.EndPoint,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags,System.TimeSpan,System.Threading.CancellationToken)">
<summary>
- Sends the given packet asynchronously within the given timeout.
+ Sends the given packet to the network.
</summary>
<param name="socket">The socket which should send the packet.</param>
<param name="remoteEndPoint">The remote endpoint to which to send the packet.</param>
<param name="packet">The packet to send.</param>
<param name="socketFlags">The socket flags associated with the write operation.</param>
<param name="timeout">
- The timespan within which to send the packet, returning <c>false</c> if this limit is exceeded.
+ The timespan within which the packet should be received. After this timespan elapses, the send task is cancelled.
</param>
+ <param name="cancellationToken">A pre-existing cancellation token that should be observed alongside the timeout.</param>
<returns>Whether the packet was successfully sent.</returns>
</member>
<member name="M:NetSharp.Connection.OnBytesReceived(System.Net.EndPoint,System.Int32)">
@@ -244,6 +233,16 @@
<param name="remoteEndPoint">The remote endpoint to which the bytes were sent.</param>
<param name="bytesSent">The number of bytes that were sent to the remote endpoint.</param>
</member>
+ <member name="E:NetSharp.Connection.BytesReceived">
+ <summary>
+ Signifies that some data has been received from the remote endpoint.
+ </summary>
+ </member>
+ <member name="E:NetSharp.Connection.BytesSent">
+ <summary>
+ Signifies that some data was sent to the remote endpoint.
+ </summary>
+ </member>
<member name="M:NetSharp.Connection.ChangeLoggingStream(System.IO.Stream,NetSharp.Logging.LogLevel)">
<summary>
Makes the client log to the given stream.
@@ -708,21 +707,22 @@
The stream to which messages will be logged.
</summary>
</member>
- <member name="F:NetSharp.Logging.Logger.writer">
+ <member name="F:NetSharp.Logging.Logger.minimumSeverity">
<summary>
- The text writer we will use to log messages to the underlying stream.
+ The minimum severity that log messages need to be logged to the underlying stream.
</summary>
</member>
- <member name="F:NetSharp.Logging.Logger.minimumSeverity">
+ <member name="F:NetSharp.Logging.Logger.writer">
<summary>
- The minimum severity that log messages need to be logged to the underlying stream.
+ The text writer we will use to log messages to the underlying stream.
</summary>
</member>
- <member name="M:NetSharp.Logging.Logger.#ctor(System.IO.Stream)">
+ <member name="M:NetSharp.Logging.Logger.#ctor(System.IO.Stream,NetSharp.Logging.LogLevel)">
<summary>
Initialises a new instance of the <see cref="T:NetSharp.Logging.Logger"/> struct.
</summary>
- <param name="streamToLogTo">The stream that the logger instance should log messages to.</param>
+ <param name="outputStream">The stream that the logger instance should log messages to.</param>
+ <param name="minimumLogSeverity">The minimum log level that will be logged to the output stream.</param>
</member>
<member name="M:NetSharp.Logging.Logger.Dispose">
<inheritdoc />
@@ -807,12 +807,6 @@
</summary>
<param name="message">The warning that should be logged.</param>
</member>
- <member name="M:NetSharp.Logging.Logger.SetMinimumLogSeverity(NetSharp.Logging.LogLevel)">
- <summary>
- Sets the minimum severity level that new messages need to be logged to the underlying stream.
- </summary>
- <param name="minimumSeverityLevel">The new minimum severity level.</param>
- </member>
<member name="T:NetSharp.Packets.Builtin.ConnectPacket">
<summary>
A simple connection request packet for the UDP protocol.
@@ -1263,11 +1257,6 @@
Provides methods for handling connected <see cref="T:NetSharp.Interfaces.IClient"/> instances.
</summary>
</member>
- <member name="F:NetSharp.Server.bindSocketCancellationTokenSource">
- <summary>
- Cancellation token source for the <see cref="M:NetSharp.Server.TryBindAsync(System.Net.IPAddress,System.Int32)"/> method.
- </summary>
- </member>
<member name="F:NetSharp.Server.complexPacketHandlers">
<summary>
Maps a packet type id to the complex packet handler for that packet type.
@@ -1279,95 +1268,84 @@
<see cref="T:NetSharp.Interfaces.IRequestPacket"/> implementors.
</summary>
</member>
- <member name="F:NetSharp.Server.simplePacketHandlers">
- <summary>
- Maps a packet type id to the simple packet handler for that packet type.
- </summary>
- </member>
- <member name="F:NetSharp.Server.PendingConnectionBacklog">
- <summary>
- The maximum number of connections that are allowed in the connection backlog.
- </summary>
- </member>
- <member name="F:NetSharp.Server.DefaultNetworkOperationTimeout">
- <summary>
- The default timeout value for all network operations.
- </summary>
- </member>
<member name="F:NetSharp.Server.serverShutdownCancellationTokenSource">
<summary>
Cancellation token source to stop handling client sockets when the server should be shut down.
</summary>
</member>
- <member name="F:NetSharp.Server.socket">
+ <member name="F:NetSharp.Server.simplePacketHandlers">
<summary>
- The <see cref="T:System.Net.Sockets.Socket"/> underlying the connection.
+ Maps a packet type id to the simple packet handler for that packet type.
</summary>
</member>
- <member name="F:NetSharp.Server.socketOptions">
+ <member name="M:NetSharp.Server.#ctor">
<summary>
- Backing field for the <see cref="P:NetSharp.Server.SocketOptions"/> property.
+ Initialises a new instance of the <see cref="T:NetSharp.Server"/> class.
</summary>
</member>
- <member name="F:NetSharp.Server.runServer">
+ <member name="M:NetSharp.Server.Finalize">
<summary>
- Whether the server should be ran.
+ Destroys an instance of the <see cref="T:NetSharp.Server"/> class.
</summary>
</member>
- <member name="M:NetSharp.Server.#ctor">
+ <member name="T:NetSharp.Server.RawRequestPacketDeserialiser">
<summary>
- Initialises a new instance of the <see cref="T:NetSharp.Server"/> class.
+ Represents a method that receives a raw packet, and deserialises it into an <see cref="T:NetSharp.Interfaces.IRequestPacket"/> implementor.
</summary>
+ <param name="rawPacket">The raw packet that was received from the network.</param>
+ <returns>The deserialised instance of the packet.</returns>
</member>
- <member name="M:NetSharp.Server.#ctor(System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,NetSharp.Utils.Socket_Options.SocketOptionManager)">
+ <member name="M:NetSharp.Server.RegisterInternalPacketHandlers">
<summary>
- Initialises a new instance of the <see cref="T:NetSharp.Server"/> class.
+ Registers packet handlers for every internal library packet.
</summary>
- <param name="socketType">The socket type for the underlying socket.</param>
- <param name="protocolType">The protocol type for the underlying socket.</param>
- <param name="socketManager">The <see cref="T:NetSharp.Utils.Socket_Options.SocketOptions"/> manager to use.</param>
</member>
- <member name="M:NetSharp.Server.Finalize">
+ <member name="F:NetSharp.Server.PendingConnectionBacklog">
<summary>
- Destroys an instance of the <see cref="T:NetSharp.Server"/> class.
+ The maximum number of connections that are allowed in the connection backlog.
</summary>
</member>
- <member name="T:NetSharp.Server.RawRequestPacketDeserialiser">
+ <member name="F:NetSharp.Server.DefaultNetworkOperationTimeout">
<summary>
- Represents a method that receives a raw packet, and deserialises it into an <see cref="T:NetSharp.Interfaces.IRequestPacket"/> implementor.
+ The default timeout value for all network operations.
</summary>
- <param name="rawPacket">The raw packet that was received from the network.</param>
- <returns>The deserialised instance of the packet.</returns>
</member>
- <member name="E:NetSharp.Server.ClientConnected">
+ <member name="F:NetSharp.Server.serverShutdownCancellationToken">
<summary>
- Signifies that a connection with a remote endpoint has been made.
+ The cancellation token that will be set when the server must be shut down.
</summary>
</member>
- <member name="E:NetSharp.Server.ClientDisconnected">
+ <member name="F:NetSharp.Server.socket">
<summary>
- Signifies that a connection with a remote endpoint has been lost.
+ The <see cref="T:System.Net.Sockets.Socket"/> underlying the connection.
</summary>
</member>
- <member name="E:NetSharp.Server.ServerStarted">
+ <member name="F:NetSharp.Server.socketOptions">
<summary>
- Signifies that the server was started and clients will start being accepted.
+ Backing field for the <see cref="P:NetSharp.Server.SocketOptions"/> property.
</summary>
</member>
- <member name="E:NetSharp.Server.ServerStopped">
+ <member name="F:NetSharp.Server.runServer">
<summary>
- Signifies that the server was stopped and clients will stop being accepted.
+ Whether the server should be ran.
</summary>
</member>
- <member name="P:NetSharp.Server.SocketOptions">
+ <member name="M:NetSharp.Server.#ctor(System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,NetSharp.Utils.Socket_Options.SocketOptionManager)">
<summary>
- The configured socket options for the underlying connection.
+ Initialises a new instance of the <see cref="T:NetSharp.Server"/> class.
</summary>
+ <param name="socketType">The socket type for the underlying socket.</param>
+ <param name="protocolType">The protocol type for the underlying socket.</param>
+ <param name="socketManager">The <see cref="T:NetSharp.Utils.Socket_Options.SocketOptions"/> manager to use.</param>
</member>
- <member name="M:NetSharp.Server.RegisterInternalPacketHandlers">
+ <member name="M:NetSharp.Server.#ctor(System.Net.Sockets.SocketType,System.Net.Sockets.ProtocolType,NetSharp.Utils.Socket_Options.SocketOptionManager,System.TimeSpan)">
<summary>
- Registers packet handlers for every internal library packet.
+ Initialises a new instance of the <see cref="T:NetSharp.Server"/> class.
</summary>
+ <param name="socketType">The socket type for the underlying socket.</param>
+ <param name="protocolType">The protocol type for the underlying socket.</param>
+ <param name="socketManager">The <see cref="T:NetSharp.Utils.Socket_Options.SocketOptions"/> manager to use.</param>
+ <param name="networkOperationTimeout">The timeout value for send and receive operations over the network.</param>
</member>
<member name="M:NetSharp.Server.DeserialiseRequestPacket(System.UInt32,NetSharp.Packets.Packet@)">
<summary>
@@ -1389,11 +1367,12 @@
</summary>
<param name="clientHandlerArgsObj">The object representing the passed <see cref="T:NetSharp.Server.ClientHandlerArgs"/> instance.</param>
</member>
- <member name="M:NetSharp.Server.HandleClientAsync(NetSharp.Server.ClientHandlerArgs)">
+ <member name="M:NetSharp.Server.HandleClientAsync(NetSharp.Server.ClientHandlerArgs,System.Threading.CancellationToken)">
<summary>
Handles a new client asynchronously.
</summary>
<param name="args">The client handler arguments that should be passed to the client handler.</param>
+ <param name="cancellationToken">Cancellation token set when the server is shutting down.</param>
</member>
<member name="M:NetSharp.Server.HandleRequestPacket(System.UInt32,NetSharp.Interfaces.IRequestPacket@,System.Net.EndPoint@)">
<summary>
@@ -1481,29 +1460,18 @@
<param name="timeout">The timeout within which to attempt the binding.</param>
<returns>Whether the binding was successful or not.</returns>
</member>
- <member name="M:NetSharp.Server.RunAsync(System.Net.EndPoint)">
- <inheritdoc />
- </member>
- <member name="M:NetSharp.Server.Shutdown">
- <inheritdoc />
- </member>
- <member name="M:NetSharp.Server.TryDeregisterComplexPacketHandler``2(NetSharp.ComplexPacketHandler{``0,``1}@)">
- <inheritdoc />
- </member>
- <member name="M:NetSharp.Server.TryDeregisterSimplePacketHandler``1(NetSharp.SimplePacketHandler{``0}@)">
- <inheritdoc />
- </member>
- <member name="M:NetSharp.Server.TryRegisterComplexPacketHandler``2(NetSharp.ComplexPacketHandler{``0,``1})">
- <inheritdoc />
- </member>
- <member name="M:NetSharp.Server.TryRegisterSimplePacketHandler``1(NetSharp.SimplePacketHandler{``0})">
- <inheritdoc />
- </member>
<member name="T:NetSharp.Server.ClientHandlerArgs">
<summary>
Holds information about the arguments passed to every client handler task.
</summary>
</member>
+ <member name="M:NetSharp.Server.ClientHandlerArgs.#ctor(System.Net.EndPoint,System.Net.Sockets.Socket)">
+ <summary>
+ Initialises a new instance of the <see cref="T:NetSharp.Server.ClientHandlerArgs"/> struct.
+ </summary>
+ <param name="remoteEndPoint">The remote endpoint of the client that should be handled.</param>
+ <param name="handlerSocket">The handler socket of the client that should be handled.</param>
+ </member>
<member name="F:NetSharp.Server.ClientHandlerArgs.ClientEndPoint">
<summary>
The remote endpoint for the client being handled.
@@ -1514,13 +1482,6 @@
The client handler socket for the client being handled. Is only set if using TCP.
</summary>
</member>
- <member name="M:NetSharp.Server.ClientHandlerArgs.#ctor(System.Net.EndPoint,System.Net.Sockets.Socket)">
- <summary>
- Initialises a new instance of the <see cref="T:NetSharp.Server.ClientHandlerArgs"/> struct.
- </summary>
- <param name="remoteEndPoint">The remote endpoint of the client that should be handled.</param>
- <param name="handlerSocket">The handler socket of the client that should be handled.</param>
- </member>
<member name="M:NetSharp.Server.ClientHandlerArgs.ForTcpClientHandler(System.Net.Sockets.Socket@)">
<summary>
Constructs a new instance of the <see cref="T:NetSharp.Server.ClientHandlerArgs"/> for a TCP client.
@@ -1533,15 +1494,66 @@
</summary>
<returns>A new instance of the <see cref="T:NetSharp.Server.ClientHandlerArgs"/>, setup for a UDP client.</returns>
</member>
+ <member name="E:NetSharp.Server.ClientConnected">
+ <summary>
+ Signifies that a connection with a remote endpoint has been made.
+ </summary>
+ </member>
+ <member name="E:NetSharp.Server.ClientDisconnected">
+ <summary>
+ Signifies that a connection with a remote endpoint has been lost.
+ </summary>
+ </member>
+ <member name="E:NetSharp.Server.ServerStarted">
+ <summary>
+ Signifies that the server was started and clients will start being accepted.
+ </summary>
+ </member>
+ <member name="E:NetSharp.Server.ServerStopped">
+ <summary>
+ Signifies that the server was stopped and clients will stop being accepted.
+ </summary>
+ </member>
+ <member name="P:NetSharp.Server.NetworkOperationTimeout">
+ <summary>
+ The timeout value for network operations such as sending bytes or receiving bytes over the network.
+ </summary>
+ </member>
+ <member name="P:NetSharp.Server.SocketOptions">
+ <summary>
+ The configured socket options for the underlying connection.
+ </summary>
+ </member>
+ <member name="M:NetSharp.Server.RunAsync(System.Net.EndPoint)">
+ <inheritdoc />
+ </member>
+ <member name="M:NetSharp.Server.Shutdown">
+ <inheritdoc />
+ </member>
+ <member name="M:NetSharp.Server.TryDeregisterComplexPacketHandler``2(NetSharp.ComplexPacketHandler{``0,``1}@)">
+ <inheritdoc />
+ </member>
+ <member name="M:NetSharp.Server.TryDeregisterSimplePacketHandler``1(NetSharp.SimplePacketHandler{``0}@)">
+ <inheritdoc />
+ </member>
+ <member name="M:NetSharp.Server.TryRegisterComplexPacketHandler``2(NetSharp.ComplexPacketHandler{``0,``1})">
+ <inheritdoc />
+ </member>
+ <member name="M:NetSharp.Server.TryRegisterSimplePacketHandler``1(NetSharp.SimplePacketHandler{``0})">
+ <inheritdoc />
+ </member>
<member name="T:NetSharp.Servers.TcpServer">
<summary>
Provides methods for TCP communication with connected <see cref="T:NetSharp.Clients.TcpClient"/> instances.
</summary>
</member>
- <member name="M:NetSharp.Servers.TcpServer.#ctor">
+ <member name="M:NetSharp.Servers.TcpServer.HandleClientAsync(NetSharp.Server.ClientHandlerArgs,System.Threading.CancellationToken)">
+ <inheritdoc />
+ </member>
+ <member name="M:NetSharp.Servers.TcpServer.#ctor(System.TimeSpan)">
<inheritdoc />
</member>
- <member name="M:NetSharp.Servers.TcpServer.HandleClientAsync(NetSharp.Server.ClientHandlerArgs)">
+ <member name="M:NetSharp.Servers.TcpServer.#ctor">
<inheritdoc />
</member>
<member name="M:NetSharp.Servers.TcpServer.RunAsync(System.Net.EndPoint)">
@@ -1552,20 +1564,23 @@
Provides methods for UDP communication with connected <see cref="T:NetSharp.Clients.UdpClient"/> instances.
</summary>
</member>
- <member name="F:NetSharp.Servers.UdpServer.activeClients">
+ <member name="F:NetSharp.Servers.UdpServer.clientChannelOptions">
<summary>
- Holds currently connected and active clients, as well as their current received packet queues.
+ The options that should be applied to every channel created to handle a client.
</summary>
</member>
- <member name="F:NetSharp.Servers.UdpServer.clientChannelOptions">
+ <member name="F:NetSharp.Servers.UdpServer.activeClients">
<summary>
- The options that should be applied to every channel created to handle a client.
+ Holds currently connected and active clients, as well as their current received packet queues.
</summary>
</member>
- <member name="M:NetSharp.Servers.UdpServer.#ctor">
+ <member name="M:NetSharp.Servers.UdpServer.HandleClientAsync(NetSharp.Server.ClientHandlerArgs,System.Threading.CancellationToken)">
<inheritdoc />
</member>
- <member name="M:NetSharp.Servers.UdpServer.HandleClientAsync(NetSharp.Server.ClientHandlerArgs)">
+ <member name="M:NetSharp.Servers.UdpServer.#ctor(System.TimeSpan)">
+ <inheritdoc />
+ </member>
+ <member name="M:NetSharp.Servers.UdpServer.#ctor">
<inheritdoc />
</member>
<member name="M:NetSharp.Servers.UdpServer.RunAsync(System.Net.EndPoint)">
@@ -1700,11 +1715,6 @@
The default port over which a connection is made.
</summary>
</member>
- <member name="F:NetSharp.Utils.Constants.UdpMaxBufferSize">
- <summary>
- The largest byte buffer that can be sent via UDP.
- </summary>
- </member>
<member name="T:NetSharp.Utils.Conversion.EndianAwareBitConverter">
<summary>
Wraps the <see cref="T:System.BitConverter"/> class to provide conversion that is endian-aware.
@@ -1780,99 +1790,85 @@
Helper class for asynchronously performing common network operations, for both the UDP and TCP protocols.
</summary>
</member>
- <member name="M:NetSharp.Utils.NetworkOperations.ReadAsync(System.Net.Sockets.Socket,System.Int32,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
+ <member name="M:NetSharp.Utils.NetworkOperations.Read(System.Net.Sockets.Socket,System.Int32,System.Net.Sockets.SocketFlags)">
<summary>
- Reads the specified amount of data asynchronously from the network, via the given socket.
- The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the read, and the given <see cref="T:System.Threading.CancellationToken"/>
- is used to allow for asynchronous task cancellation.
+ Reads the specified amount of data from the network, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the read.
</summary>
<param name="socket">The socket which should read data from the network.</param>
<param name="count">The number of bytes to read from the network.</param>
<param name="socketFlags">The socket flags associated with the receive operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
<returns>The result of the receive operation.</returns>
</member>
- <member name="M:NetSharp.Utils.NetworkOperations.ReadFromAsync(System.Net.Sockets.Socket,System.Int32,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
+ <member name="M:NetSharp.Utils.NetworkOperations.ReadFrom(System.Net.Sockets.Socket,System.Int32,System.Net.EndPoint,System.Net.Sockets.SocketFlags)">
<summary>
- Reads a datagram asynchronously from the given remote endpoint, via the given socket.
- The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the read, and the given <see cref="T:System.Threading.CancellationToken"/>
- is used to allow for asynchronous task cancellation.
+ Reads a datagram segment of the given length from the given remote endpoint, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the read.
</summary>
<param name="socket">The socket which should read data from the network.</param>
<param name="count">The number of bytes to read from the network.</param>
<param name="remoteEndPoint">The remote endpoint from which data should be read.</param>
<param name="socketFlags">The socket flags associated with the receive operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
<returns>The result of the receive operation.</returns>
</member>
- <member name="M:NetSharp.Utils.NetworkOperations.ReadPacketAsync(System.Net.Sockets.Socket,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
+ <member name="M:NetSharp.Utils.NetworkOperations.Write(System.Net.Sockets.Socket,System.ReadOnlyMemory{System.Byte},System.Net.Sockets.SocketFlags)">
<summary>
- Reads a packet asynchronously from network, via the given socket. The given <see cref="T:System.Net.Sockets.SocketFlags"/> are
- associated with the read, and the given <see cref="T:System.Threading.CancellationToken"/> is used to allow for asynchronous
- task cancellation.
+ Writes the given data buffer to the network, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the write, and the given <see cref="T:System.Threading.CancellationToken"/>
+ is used to allow for asynchronous task cancellation.
+ </summary>
+ <param name="socket">The socket which should write data to the network.</param>
+ <param name="buffer">The buffer that should be written to the network.</param>
+ <param name="socketFlags">The socket flags associated with the send operation.</param>
+ </member>
+ <member name="M:NetSharp.Utils.NetworkOperations.WriteTo(System.Net.Sockets.Socket,System.Net.EndPoint,System.ReadOnlyMemory{System.Byte},System.Net.Sockets.SocketFlags)">
+ <summary>
+ Writes the given data buffer to the given remote endpoint, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the write, and the given <see cref="T:System.Threading.CancellationToken"/>
+ is used to allow for asynchronous task cancellation.
+ </summary>
+ <param name="socket">The socket which should write data to the network.</param>
+ <param name="remoteEndPoint">The remote endpoint to which data should be written.</param>
+ <param name="buffer">The buffer that should be written to the network.</param>
+ <param name="socketFlags">The socket flags associated with the send operation.</param>
+ </member>
+ <member name="M:NetSharp.Utils.NetworkOperations.ReadPacket(System.Net.Sockets.Socket,System.Net.Sockets.SocketFlags)">
+ <summary>
+ Reads a packet from network, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the read.
</summary>
<param name="socket">The socket which should read the packet from the network.</param>
<param name="socketFlags">The socket flags associated with the receive operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
<returns>The read packet.</returns>
</member>
- <member name="M:NetSharp.Utils.NetworkOperations.ReadPacketFromAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
+ <member name="M:NetSharp.Utils.NetworkOperations.ReadPacketFrom(System.Net.Sockets.Socket,System.Net.EndPoint,System.Net.Sockets.SocketFlags)">
<summary>
- Reads a packet asynchronously from the given remote endpoint, via the given socket. The given
- <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the read, and the given <see cref="T:System.Threading.CancellationToken"/> is
- used to allow for asynchronous task cancellation.
+ Reads a packet from the given remote endpoint, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the read.
</summary>
<param name="socket">The socket which should read the packet from the network.</param>
<param name="remoteEndPoint">The remote endpoint from which a packet should be read.</param>
<param name="socketFlags">The socket flags associated with the receive operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
<returns>The read packet and associated transmission results.</returns>
</member>
- <member name="M:NetSharp.Utils.NetworkOperations.WriteAsync(System.Net.Sockets.Socket,System.ReadOnlyMemory{System.Byte},System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
+ <member name="M:NetSharp.Utils.NetworkOperations.WritePacket(System.Net.Sockets.Socket,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags)">
<summary>
- Writes the given buffer asynchronously to the network, via the given socket.
- The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the write, and the given <see cref="T:System.Threading.CancellationToken"/>
- is used to allow for asynchronous task cancellation.
- </summary>
- <param name="socket">The socket which should write data to the network.</param>
- <param name="buffer">The buffer that should be written to the network.</param>
- <param name="socketFlags">The socket flags associated with the send operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
- </member>
- <member name="M:NetSharp.Utils.NetworkOperations.WritePacketAsync(System.Net.Sockets.Socket,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
- <summary>
- Writes the given packet asynchronously to the network, via the given socket. The given <see cref="T:System.Net.Sockets.SocketFlags"/>
- are associated with the write, and the given <see cref="T:System.Threading.CancellationToken"/> is used to allow for asynchronous
- task cancellation.
+ Writes the given packet to the network, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the write.
</summary>
<param name="socket">The socket which should write data to the network.</param>
<param name="packet">The packet that should be written to the network.</param>
<param name="socketFlags">The socket flags associated with the send operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
</member>
- <member name="M:NetSharp.Utils.NetworkOperations.WritePacketToAsync(System.Net.Sockets.Socket,System.Net.EndPoint,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
+ <member name="M:NetSharp.Utils.NetworkOperations.WritePacketTo(System.Net.Sockets.Socket,System.Net.EndPoint,NetSharp.Packets.Packet,System.Net.Sockets.SocketFlags)">
<summary>
- Writes the given packet asynchronously to the given remote endpoint, via the given socket.
- The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the write, and the given <see cref="T:System.Threading.CancellationToken"/>
- is used to allow for asynchronous task cancellation.
+ Writes the given packet to the given remote endpoint, via the given socket.
+ The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the write.
</summary>
<param name="socket">The socket which should write data to the network.</param>
<param name="remoteEndPoint">The remote endpoint to which data should be written.</param>
<param name="packet">The packet that should be written to the remote endpoint.</param>
<param name="socketFlags">The socket flags associated with the send operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
- </member>
- <member name="M:NetSharp.Utils.NetworkOperations.WriteToAsync(System.Net.Sockets.Socket,System.Net.EndPoint,System.ReadOnlyMemory{System.Byte},System.Net.Sockets.SocketFlags,System.Threading.CancellationToken)">
- <summary>
- Writes the given buffer asynchronously to the given remote endpoint, via the given socket.
- The given <see cref="T:System.Net.Sockets.SocketFlags"/> are associated with the write, and the given <see cref="T:System.Threading.CancellationToken"/>
- is used to allow for asynchronous task cancellation.
- </summary>
- <param name="socket">The socket which should write data to the network.</param>
- <param name="remoteEndPoint">The remote endpoint to which data should be written.</param>
- <param name="buffer">The buffer that should be written to the network.</param>
- <param name="socketFlags">The socket flags associated with the send operation.</param>
- <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
</member>
<member name="T:NetSharp.Utils.Socket_Options.DefaultSocketOptions">
<summary>
diff --git a/NetSharp/NetSharp/Packets/Packet.cs b/NetSharp/NetSharp/Packets/Packet.cs
@@ -63,7 +63,7 @@ namespace NetSharp.Packets
{
Span<byte> serialisedType = buffer.Slice(sizeof(int), sizeof(uint)).Span;
Span<byte> serialisedErrorCode = buffer.Slice(sizeof(int) + sizeof(uint), sizeof(uint)).Span;
- Memory<byte> serialisedData = buffer.Slice(HeaderSize);
+ ReadOnlyMemory<byte> serialisedData = buffer.Slice(HeaderSize);
return new Packet(serialisedData,
EndianAwareBitConverter.ToUInt32(serialisedType),
diff --git a/NetSharp/NetSharp/Server.cs b/NetSharp/NetSharp/Server.cs
@@ -40,11 +40,6 @@ namespace NetSharp
public abstract class Server : Connection, IServer, IDisposable
{
/// <summary>
- /// Cancellation token source for the <see cref="TryBindAsync(IPAddress,int)"/> method.
- /// </summary>
- private readonly CancellationTokenSource bindSocketCancellationTokenSource;
-
- /// <summary>
/// Maps a packet type id to the complex packet handler for that packet type.
/// </summary>
private readonly ConcurrentDictionary<uint, Func<IRequestPacket, EndPoint, IResponsePacket<IRequestPacket>>>
@@ -57,39 +52,14 @@ namespace NetSharp
private readonly ConcurrentDictionary<uint, RawRequestPacketDeserialiser> requestPacketDeserialisers;
/// <summary>
- /// Maps a packet type id to the simple packet handler for that packet type.
- /// </summary>
- private readonly ConcurrentDictionary<uint, Action<IRequestPacket, EndPoint>> simplePacketHandlers;
-
- /// <summary>
- /// The maximum number of connections that are allowed in the connection backlog.
- /// </summary>
- protected const int PendingConnectionBacklog = 100;
-
- /// <summary>
- /// The default timeout value for all network operations.
- /// </summary>
- protected static readonly TimeSpan DefaultNetworkOperationTimeout = TimeSpan.FromMilliseconds(10_000);
-
- /// <summary>
/// Cancellation token source to stop handling client sockets when the server should be shut down.
/// </summary>
- protected readonly CancellationTokenSource serverShutdownCancellationTokenSource;
+ private readonly CancellationTokenSource serverShutdownCancellationTokenSource;
/// <summary>
- /// The <see cref="Socket"/> underlying the connection.
- /// </summary>
- protected readonly Socket socket;
-
- /// <summary>
- /// Backing field for the <see cref="SocketOptions"/> property.
- /// </summary>
- protected readonly SocketOptions socketOptions;
-
- /// <summary>
- /// Whether the server should be ran.
+ /// Maps a packet type id to the simple packet handler for that packet type.
/// </summary>
- protected volatile bool runServer;
+ private readonly ConcurrentDictionary<uint, Action<IRequestPacket, EndPoint>> simplePacketHandlers;
/// <summary>
/// Initialises a new instance of the <see cref="Server"/> class.
@@ -97,7 +67,8 @@ namespace NetSharp
private Server()
{
serverShutdownCancellationTokenSource = new CancellationTokenSource();
- bindSocketCancellationTokenSource = new CancellationTokenSource();
+
+ serverShutdownCancellationToken = serverShutdownCancellationTokenSource.Token;
requestPacketDeserialisers = new ConcurrentDictionary<uint, RawRequestPacketDeserialiser>();
@@ -112,24 +83,6 @@ namespace NetSharp
}
/// <summary>
- /// Initialises a new instance of the <see cref="Server"/> class.
- /// </summary>
- /// <param name="socketType">The socket type for the underlying socket.</param>
- /// <param name="protocolType">The protocol type for the underlying socket.</param>
- /// <param name="socketManager">The <see cref="Utils.Socket_Options.SocketOptions"/> manager to use.</param>
- protected Server(SocketType socketType, ProtocolType protocolType, SocketOptionManager socketManager) : this()
- {
- socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType);
-
- socketOptions = socketManager switch
- {
- SocketOptionManager.Tcp => new TcpSocketOptions(ref socket) as SocketOptions,
- SocketOptionManager.Udp => new UdpSocketOptions(ref socket) as SocketOptions,
- _ => new DefaultSocketOptions(ref socket),
- };
- }
-
- /// <summary>
/// Destroys an instance of the <see cref="Server"/> class.
/// </summary>
~Server()
@@ -145,35 +98,6 @@ namespace NetSharp
private delegate IRequestPacket RawRequestPacketDeserialiser(in Packet rawPacket);
/// <summary>
- /// Signifies that a connection with a remote endpoint has been made.
- /// </summary>
- public event Action<EndPoint>? ClientConnected;
-
- //protected IResponsePacket<IRequestPacket> DeserialiseResponsePacket(in Packet)
- /// <summary>
- /// Signifies that a connection with a remote endpoint has been lost.
- /// </summary>
- public event Action<EndPoint>? ClientDisconnected;
-
- /// <summary>
- /// Signifies that the server was started and clients will start being accepted.
- /// </summary>
- public event Action? ServerStarted;
-
- /// <summary>
- /// Signifies that the server was stopped and clients will stop being accepted.
- /// </summary>
- public event Action? ServerStopped;
-
- /// <summary>
- /// The configured socket options for the underlying connection.
- /// </summary>
- public SocketOptions SocketOptions
- {
- get { return socketOptions; }
- }
-
- /// <summary>
/// Registers packet handlers for every internal library packet.
/// </summary>
private void RegisterInternalPacketHandlers()
@@ -211,6 +135,69 @@ namespace NetSharp
}
/// <summary>
+ /// The maximum number of connections that are allowed in the connection backlog.
+ /// </summary>
+ protected const int PendingConnectionBacklog = 100;
+
+ /// <summary>
+ /// The default timeout value for all network operations.
+ /// </summary>
+ protected static readonly TimeSpan DefaultNetworkOperationTimeout = TimeSpan.FromMilliseconds(10_000);
+
+ /// <summary>
+ /// The cancellation token that will be set when the server must be shut down.
+ /// </summary>
+ protected readonly CancellationToken serverShutdownCancellationToken;
+
+ /// <summary>
+ /// The <see cref="Socket"/> underlying the connection.
+ /// </summary>
+ protected readonly Socket socket;
+
+ /// <summary>
+ /// Backing field for the <see cref="SocketOptions"/> property.
+ /// </summary>
+ protected readonly SocketOptions socketOptions;
+
+ /// <summary>
+ /// Whether the server should be ran.
+ /// </summary>
+ protected volatile bool runServer;
+
+ /// <summary>
+ /// Initialises a new instance of the <see cref="Server"/> class.
+ /// </summary>
+ /// <param name="socketType">The socket type for the underlying socket.</param>
+ /// <param name="protocolType">The protocol type for the underlying socket.</param>
+ /// <param name="socketManager">The <see cref="Utils.Socket_Options.SocketOptions"/> manager to use.</param>
+ protected Server(SocketType socketType, ProtocolType protocolType, SocketOptionManager socketManager)
+ : this(socketType, protocolType, socketManager, DefaultNetworkOperationTimeout)
+ {
+ }
+
+ /// <summary>
+ /// Initialises a new instance of the <see cref="Server"/> class.
+ /// </summary>
+ /// <param name="socketType">The socket type for the underlying socket.</param>
+ /// <param name="protocolType">The protocol type for the underlying socket.</param>
+ /// <param name="socketManager">The <see cref="Utils.Socket_Options.SocketOptions"/> manager to use.</param>
+ /// <param name="networkOperationTimeout">The timeout value for send and receive operations over the network.</param>
+ protected Server(SocketType socketType, ProtocolType protocolType, SocketOptionManager socketManager,
+ TimeSpan networkOperationTimeout) : this()
+ {
+ socket = new Socket(AddressFamily.InterNetwork, socketType, protocolType);
+
+ socketOptions = socketManager switch
+ {
+ SocketOptionManager.Tcp => new TcpSocketOptions(ref socket) as SocketOptions,
+ SocketOptionManager.Udp => new UdpSocketOptions(ref socket) as SocketOptions,
+ _ => new DefaultSocketOptions(ref socket),
+ };
+
+ NetworkOperationTimeout = networkOperationTimeout;
+ }
+
+ /// <summary>
/// Deserialises the given <see cref="Packet"/> struct into an <see cref="IRequestPacket"/> implementor.
/// </summary>
/// <param name="packetType">The type id of packet that we should deserialise to.</param>
@@ -237,8 +224,8 @@ namespace NetSharp
{
if (disposing)
{
- bindSocketCancellationTokenSource?.Cancel();
- bindSocketCancellationTokenSource?.Dispose();
+ serverShutdownCancellationTokenSource?.Cancel();
+ serverShutdownCancellationTokenSource?.Dispose();
socket.Dispose();
}
@@ -256,10 +243,10 @@ namespace NetSharp
try
{
- await HandleClientAsync(clientHandlerArgs);
+ await HandleClientAsync(clientHandlerArgs, serverShutdownCancellationTokenSource.Token);
}
- catch (TaskCanceledException) { logger.LogMessage("Client handling was cancelled via a task cancellation."); }
- catch (OperationCanceledException) { logger.LogMessage("Client handling was cancelled via an operation cancellation."); }
+ catch (TaskCanceledException) { logger.LogWarning("Client handling was cancelled via a task cancellation."); }
+ catch (OperationCanceledException) { logger.LogWarning("Client handling was cancelled via an operation cancellation."); }
catch (Exception ex)
{
logger.LogException("Exception during client handling", ex);
@@ -282,7 +269,8 @@ namespace NetSharp
/// Handles a new client asynchronously.
/// </summary>
/// <param name="args">The client handler arguments that should be passed to the client handler.</param>
- protected abstract Task HandleClientAsync(ClientHandlerArgs args);
+ /// <param name="cancellationToken">Cancellation token set when the server is shutting down.</param>
+ protected abstract Task HandleClientAsync(ClientHandlerArgs args, CancellationToken cancellationToken);
/// <summary>
/// Handles the given request packet with a registered packet handler. In this case, a complex packet handler
@@ -312,9 +300,9 @@ namespace NetSharp
return null;
}
- #if DEBUG
+#if DEBUG
logger.LogWarning($"No packet handler was registered for packet of type {packetType}");
- #endif
+#endif
}
catch (Exception ex)
{
@@ -411,16 +399,18 @@ namespace NetSharp
/// <returns>Whether the binding was successful or not.</returns>
protected async Task<bool> TryBindAsync(EndPoint localEndPoint, TimeSpan timeout)
{
+ CancellationTokenSource timeoutCancellationTokenSource = new CancellationTokenSource(timeout);
+ CancellationTokenSource cts =
+ CancellationTokenSource.CreateLinkedTokenSource(timeoutCancellationTokenSource.Token, serverShutdownCancellationToken);
+
try
{
- bindSocketCancellationTokenSource.CancelAfter(timeout);
-
return await Task.Run(() =>
{
socket.Bind(localEndPoint);
return true;
- }, bindSocketCancellationTokenSource.Token);
+ }, cts.Token);
}
catch (TaskCanceledException)
{
@@ -431,6 +421,91 @@ namespace NetSharp
logger.LogException($"Socket exception on binding socket to {localEndPoint}:", ex);
return false;
}
+ finally
+ {
+ cts.Dispose();
+ timeoutCancellationTokenSource.Dispose();
+ }
+ }
+
+ /// <summary>
+ /// Holds information about the arguments passed to every client handler task.
+ /// </summary>
+ protected readonly struct ClientHandlerArgs
+ {
+ /// <summary>
+ /// Initialises a new instance of the <see cref="ClientHandlerArgs"/> struct.
+ /// </summary>
+ /// <param name="remoteEndPoint">The remote endpoint of the client that should be handled.</param>
+ /// <param name="handlerSocket">The handler socket of the client that should be handled.</param>
+ private ClientHandlerArgs(EndPoint remoteEndPoint, Socket? handlerSocket)
+ {
+ ClientEndPoint = remoteEndPoint;
+
+ ClientSocket = handlerSocket;
+ }
+
+ /// <summary>
+ /// The remote endpoint for the client being handled.
+ /// </summary>
+ public readonly EndPoint ClientEndPoint;
+
+ /// <summary>
+ /// The client handler socket for the client being handled. Is only set if using TCP.
+ /// </summary>
+ public readonly Socket? ClientSocket;
+
+ /// <summary>
+ /// Constructs a new instance of the <see cref="ClientHandlerArgs"/> for a TCP client.
+ /// </summary>
+ /// <returns>A new instance of the <see cref="ClientHandlerArgs"/>, setup for a TCP client.</returns>
+ public static ClientHandlerArgs ForTcpClientHandler(in Socket clientHandlerSocket)
+ {
+ return new ClientHandlerArgs(clientHandlerSocket.RemoteEndPoint, clientHandlerSocket);
+ }
+
+ /// <summary>
+ /// Constructs a new instance of the <see cref="ClientHandlerArgs"/> for a UDP client.
+ /// </summary>
+ /// <returns>A new instance of the <see cref="ClientHandlerArgs"/>, setup for a UDP client.</returns>
+ public static ClientHandlerArgs ForUdpClientHandler(in EndPoint clientEndPoint)
+ {
+ return new ClientHandlerArgs(clientEndPoint, null);
+ }
+ }
+
+ /// <summary>
+ /// Signifies that a connection with a remote endpoint has been made.
+ /// </summary>
+ public event Action<EndPoint>? ClientConnected;
+
+ //protected IResponsePacket<IRequestPacket> DeserialiseResponsePacket(in Packet)
+ /// <summary>
+ /// Signifies that a connection with a remote endpoint has been lost.
+ /// </summary>
+ public event Action<EndPoint>? ClientDisconnected;
+
+ /// <summary>
+ /// Signifies that the server was started and clients will start being accepted.
+ /// </summary>
+ public event Action? ServerStarted;
+
+ /// <summary>
+ /// Signifies that the server was stopped and clients will stop being accepted.
+ /// </summary>
+ public event Action? ServerStopped;
+
+ /// <summary>
+ /// The timeout value for network operations such as sending bytes or receiving bytes over the network.
+ /// </summary>
+ public TimeSpan NetworkOperationTimeout { get; protected set; }
+
+ /// <summary>
+ /// The configured socket options for the underlying connection.
+ /// </summary>
+ public SocketOptions SocketOptions
+ {
+ get { return socketOptions; }
}
/// <inheritdoc />
@@ -572,51 +647,5 @@ namespace NetSharp
return false;
}
-
- /// <summary>
- /// Holds information about the arguments passed to every client handler task.
- /// </summary>
- protected readonly struct ClientHandlerArgs
- {
- /// <summary>
- /// The remote endpoint for the client being handled.
- /// </summary>
- public readonly EndPoint ClientEndPoint;
-
- /// <summary>
- /// The client handler socket for the client being handled. Is only set if using TCP.
- /// </summary>
- public readonly Socket? ClientSocket;
-
- /// <summary>
- /// Initialises a new instance of the <see cref="ClientHandlerArgs"/> struct.
- /// </summary>
- /// <param name="remoteEndPoint">The remote endpoint of the client that should be handled.</param>
- /// <param name="handlerSocket">The handler socket of the client that should be handled.</param>
- private ClientHandlerArgs(EndPoint remoteEndPoint, Socket? handlerSocket)
- {
- ClientEndPoint = remoteEndPoint;
-
- ClientSocket = handlerSocket;
- }
-
- /// <summary>
- /// Constructs a new instance of the <see cref="ClientHandlerArgs"/> for a TCP client.
- /// </summary>
- /// <returns>A new instance of the <see cref="ClientHandlerArgs"/>, setup for a TCP client.</returns>
- public static ClientHandlerArgs ForTcpClientHandler(in Socket clientHandlerSocket)
- {
- return new ClientHandlerArgs(clientHandlerSocket.RemoteEndPoint, clientHandlerSocket);
- }
-
- /// <summary>
- /// Constructs a new instance of the <see cref="ClientHandlerArgs"/> for a UDP client.
- /// </summary>
- /// <returns>A new instance of the <see cref="ClientHandlerArgs"/>, setup for a UDP client.</returns>
- public static ClientHandlerArgs ForUdpClientHandler(in EndPoint clientEndPoint)
- {
- return new ClientHandlerArgs(clientEndPoint, null);
- }
- }
}
}
\ No newline at end of file
diff --git a/NetSharp/NetSharp/Servers/TcpServer.cs b/NetSharp/NetSharp/Servers/TcpServer.cs
@@ -17,15 +17,9 @@ namespace NetSharp.Servers
public sealed class TcpServer : Server
{
/// <inheritdoc />
- public TcpServer() : base(SocketType.Stream, ProtocolType.Tcp, SocketOptionManager.Tcp)
- {
- }
-
- /// <inheritdoc />
- protected override async Task HandleClientAsync(ClientHandlerArgs args)
+ protected override async Task HandleClientAsync(ClientHandlerArgs args, CancellationToken cancellationToken)
{
Socket clientHandlerSocket = args.ClientSocket ?? new Socket(SocketType.Unknown, ProtocolType.Unknown);
-
EndPoint remoteEp = clientHandlerSocket.RemoteEndPoint;
logger.LogMessage($"Initialised client handler for client socket: [Remote EP: {remoteEp}]");
@@ -35,12 +29,14 @@ namespace NetSharp.Servers
do
{
// receive a single raw packet from the network
- Packet rawRequest =
- await DoReceivePacketAsync(clientHandlerSocket, SocketFlags.None, Timeout.InfiniteTimeSpan);
+ Packet rawRequest = await DoReceivePacketAsync(clientHandlerSocket, SocketFlags.None,
+ Timeout.InfiniteTimeSpan, cancellationToken);
- if (rawRequest.Equals(NullPacket) || rawRequest.Type == PacketRegistry.GetPacketId<DisconnectPacket>())
+ if (rawRequest.Equals(NullPacket) ||
+ rawRequest.Type == PacketRegistry.GetPacketId<DisconnectPacket>())
{
- logger.LogMessage($"Received a disconnect packet from client socket: [Remote EP: {remoteEp}]");
+ logger.LogMessage(
+ $"Received a disconnect packet from client socket: [Remote EP: {remoteEp}]");
break;
}
@@ -65,39 +61,49 @@ namespace NetSharp.Servers
if (responsePacketType == null)
{
- logger.LogError($"Response packet type for request packet of type {requestPacketType} is null");
+ logger.LogError(
+ $"Response packet type for request packet of type {requestPacketType} is null");
continue;
}
uint responsePacketTypeId = PacketRegistry.GetPacketId(responsePacketType);
responsePacket.BeforeSerialisation();
- Packet rawResponse = new Packet(responsePacket.Serialise(), responsePacketTypeId, NetworkErrorCode.Ok);
+ Packet rawResponse = new Packet(responsePacket.Serialise(), responsePacketTypeId,
+ NetworkErrorCode.Ok);
// echo back the processed raw response to the network
- bool sentCorrectly =
- await DoSendPacketAsync(clientHandlerSocket, rawResponse, SocketFlags.None, DefaultNetworkOperationTimeout);
+ bool sentCorrectly = await DoSendPacketAsync(clientHandlerSocket, rawResponse, SocketFlags.None,
+ NetworkOperationTimeout, cancellationToken);
if (!sentCorrectly)
{
- logger.LogMessage($"Could not send response back to client socket: [Remote EP: {remoteEp}]");
+ logger.LogMessage(
+ $"Could not send response back to client socket: [Remote EP: {remoteEp}]");
break;
}
logger.LogMessage($"Sent {rawResponse.TotalSize} bytes to {remoteEp}");
} while (true);
-
- logger.LogMessage($"Stopping client handler for client socket: [Remote EP: {remoteEp}]");
}
- catch (TaskCanceledException) { logger.LogMessage("Client handling was cancelled via a task cancellation."); }
- catch (OperationCanceledException) { logger.LogMessage("Client handling was cancelled via an operation cancellation."); }
- catch (Exception ex)
+ finally
{
- logger.LogException("Exception during client socket handling:", ex);
+ logger.LogMessage($"Stopping client handler for client socket: [Remote EP: {remoteEp}]");
}
}
/// <inheritdoc />
+ public TcpServer(TimeSpan networkOperationTimeout) : base(SocketType.Stream, ProtocolType.Tcp,
+ SocketOptionManager.Tcp, networkOperationTimeout)
+ {
+ }
+
+ /// <inheritdoc />
+ public TcpServer() : this(DefaultNetworkOperationTimeout)
+ {
+ }
+
+ /// <inheritdoc />
public override async Task RunAsync(EndPoint localEndPoint)
{
bool bound = await TryBindAsync(localEndPoint);
@@ -120,10 +126,8 @@ namespace NetSharp.Servers
Socket clientSocket = await socket.AcceptAsync();
ClientHandlerArgs args = ClientHandlerArgs.ForTcpClientHandler(in clientSocket);
- await Task.Factory.StartNew(DoHandleClientAsync, args,
- serverShutdownCancellationTokenSource.Token,
- TaskCreationOptions.LongRunning,
- TaskScheduler.Current);
+ await Task.Factory.StartNew(DoHandleClientAsync, args, serverShutdownCancellationToken,
+ TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
OnServerStopped();
diff --git a/NetSharp/NetSharp/Servers/UdpServer.cs b/NetSharp/NetSharp/Servers/UdpServer.cs
@@ -2,6 +2,7 @@
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
+using System.Threading;
using System.Threading.Channels;
using System.Threading.Tasks;
using NetSharp.Interfaces;
@@ -18,27 +19,21 @@ namespace NetSharp.Servers
public sealed class UdpServer : Server
{
/// <summary>
- /// Holds currently connected and active clients, as well as their current received packet queues.
- /// </summary>
- private readonly ConcurrentDictionary<EndPoint, Channel<Packet>> activeClients;
-
- /// <summary>
/// The options that should be applied to every channel created to handle a client.
/// </summary>
private static readonly UnboundedChannelOptions clientChannelOptions = new UnboundedChannelOptions
- {
- SingleReader = true,
- SingleWriter = true
- };
-
- /// <inheritdoc />
- public UdpServer() : base(SocketType.Dgram, ProtocolType.Udp, SocketOptionManager.Udp)
{
- activeClients = new ConcurrentDictionary<EndPoint, Channel<Packet>>();
- }
+ SingleReader = true,
+ SingleWriter = true
+ };
+
+ /// <summary>
+ /// Holds currently connected and active clients, as well as their current received packet queues.
+ /// </summary>
+ private readonly ConcurrentDictionary<EndPoint, Channel<Packet>> activeClients;
/// <inheritdoc />
- protected override async Task HandleClientAsync(ClientHandlerArgs args)
+ protected override async Task HandleClientAsync(ClientHandlerArgs args, CancellationToken cancellationToken)
{
EndPoint clientEndPoint = args.ClientEndPoint;
Channel<Packet> clientPacketBuffer = activeClients[clientEndPoint];
@@ -50,11 +45,13 @@ namespace NetSharp.Servers
do
{
// receive a single raw packet from the network
- Packet rawRequest = await clientPacketBuffer.Reader.ReadAsync(serverShutdownCancellationTokenSource.Token);
+ Packet rawRequest = await clientPacketBuffer.Reader.ReadAsync(cancellationToken);
- if (rawRequest.Equals(NullPacket) || rawRequest.Type == PacketRegistry.GetPacketId<DisconnectPacket>())
+ if (rawRequest.Equals(NullPacket) ||
+ rawRequest.Type == PacketRegistry.GetPacketId<DisconnectPacket>())
{
- logger.LogMessage($"Received a disconnect packet from client socket: [Remote EP: {clientEndPoint}]");
+ logger.LogMessage(
+ $"Received a disconnect packet from client socket: [Remote EP: {clientEndPoint}]");
break;
}
@@ -75,45 +72,57 @@ namespace NetSharp.Servers
if (responsePacketType == null)
{
- logger.LogError($"Response packet type for request packet of type {requestPacketType} is null");
+ logger.LogError(
+ $"Response packet type for request packet of type {requestPacketType} is null");
continue;
}
uint responsePacketTypeId = PacketRegistry.GetPacketId(responsePacketType);
responsePacket.BeforeSerialisation();
- Packet rawResponse = new Packet(responsePacket.Serialise(), responsePacketTypeId, NetworkErrorCode.Ok);
+ Packet rawResponse = new Packet(responsePacket.Serialise(), responsePacketTypeId,
+ NetworkErrorCode.Ok);
// echo back the processed raw response to the network
- bool sentCorrectly =
- await DoSendPacketToAsync(socket, clientEndPoint, rawResponse, SocketFlags.None,
- DefaultNetworkOperationTimeout);
+ bool sentCorrectly = await DoSendPacketToAsync(socket, clientEndPoint, rawResponse, SocketFlags.None,
+ NetworkOperationTimeout, cancellationToken);
if (!sentCorrectly)
{
- logger.LogWarning($"Could not send response back to client socket: [Remote EP: {clientEndPoint}]");
+ logger.LogWarning(
+ $"Could not send response back to client socket: [Remote EP: {clientEndPoint}]");
break;
}
} while (true);
-
+ }
+ finally
+ {
logger.LogMessage($"Stopping client handler for client socket: [Remote EP: {clientEndPoint}]");
if (activeClients.TryRemove(clientEndPoint, out Channel<Packet> packetChannel))
{
packetChannel.Writer.Complete();
- logger.LogMessage($"Shutting down packet channel for client socket: [Remote EP: {clientEndPoint}]");
+ logger.LogMessage(
+ $"Shutting down packet channel for client socket: [Remote EP: {clientEndPoint}]");
}
else
{
- logger.LogMessage($"Couldn't shut down packet channel for client socket: [Remote EP: {clientEndPoint}]");
+ logger.LogMessage(
+ $"Couldn't shut down packet channel for client socket: [Remote EP: {clientEndPoint}]");
}
}
- catch (TaskCanceledException) { logger.LogMessage("Client handling was cancelled via a task cancellation."); }
- catch (OperationCanceledException) { logger.LogMessage("Client handling was cancelled via an operation cancellation."); }
- catch (Exception ex)
- {
- logger.LogException("Exception during client socket handling:", ex);
- }
+ }
+
+ /// <inheritdoc />
+ public UdpServer(TimeSpan networkOperationTimeout) : base(SocketType.Dgram, ProtocolType.Udp, SocketOptionManager.Udp,
+ networkOperationTimeout)
+ {
+ activeClients = new ConcurrentDictionary<EndPoint, Channel<Packet>>();
+ }
+
+ /// <inheritdoc />
+ public UdpServer() : this(DefaultNetworkOperationTimeout)
+ {
}
/// <inheritdoc />
@@ -134,24 +143,23 @@ namespace NetSharp.Servers
{
EndPoint nullEndPoint = new IPEndPoint(IPAddress.Any, 0);
(Packet request, TransmissionResult packetResult) =
- await DoReceivePacketFromAsync(socket, nullEndPoint, SocketFlags.None, DefaultNetworkOperationTimeout);
+ await DoReceivePacketFromAsync(socket, nullEndPoint, SocketFlags.None, Timeout.InfiniteTimeSpan,
+ serverShutdownCancellationToken);
EndPoint clientEndPoint = packetResult.RemoteEndPoint;
if (request.Equals(NullPacket) || packetResult.Equals(NullTransmissionResult))
{
continue;
}
-
+
if (!activeClients.ContainsKey(clientEndPoint))
{
ClientHandlerArgs args = ClientHandlerArgs.ForUdpClientHandler(in clientEndPoint);
activeClients.TryAdd(clientEndPoint, Channel.CreateUnbounded<Packet>(clientChannelOptions));
- await Task.Factory.StartNew(DoHandleClientAsync, args,
- serverShutdownCancellationTokenSource.Token,
- TaskCreationOptions.LongRunning,
- TaskScheduler.Current);
+ await Task.Factory.StartNew(DoHandleClientAsync, args, serverShutdownCancellationToken,
+ TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
await activeClients[clientEndPoint].Writer.WriteAsync(request);
diff --git a/NetSharp/NetSharp/Utils/Constants.cs b/NetSharp/NetSharp/Utils/Constants.cs
@@ -9,10 +9,5 @@
/// The default port over which a connection is made.
/// </summary>
internal const int DefaultPort = 12374;
-
- /// <summary>
- /// The largest byte buffer that can be sent via UDP.
- /// </summary>
- internal const int UdpMaxBufferSize = 60_000;
}
}
\ No newline at end of file
diff --git a/NetSharp/NetSharp/Utils/Conversion/EndianAwareBitConverter.cs b/NetSharp/NetSharp/Utils/Conversion/EndianAwareBitConverter.cs
@@ -23,120 +23,140 @@ namespace NetSharp.Utils.Conversion
}
/// <inheritdoc cref="BitConverter.GetBytes(bool)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(bool value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(char)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(char value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(double)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(double value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(float)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(float value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(int)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(int value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(long)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(long value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(short)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(short value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(uint)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(uint value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(ulong)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(ulong value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.GetBytes(ushort)"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> GetBytes(ushort value, bool littleEndian = false)
{
return ReverseAsNeeded(BitConverter.GetBytes(value), littleEndian);
}
/// <inheritdoc cref="BitConverter.ToBoolean(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool ToBoolean(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToBoolean(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToChar(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static char ToChar(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToChar(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToDouble(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static double ToDouble(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToDouble(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToInt16(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static short ToInt16(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToInt16(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToInt32(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ToInt32(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToInt32(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToInt64(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static long ToInt64(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToInt64(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToSingle(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float ToSingle(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToSingle(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToUInt16(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ushort ToUInt16(byte[] bytes, bool littleEndian = false)
{
return BitConverter.ToUInt16(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToUInt32(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static uint ToUInt32(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToUInt32(ReverseAsNeeded(bytes, littleEndian));
}
/// <inheritdoc cref="BitConverter.ToUInt64(ReadOnlySpan{byte})"/>
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ulong ToUInt64(Span<byte> bytes, bool littleEndian = false)
{
return BitConverter.ToUInt64(ReverseAsNeeded(bytes, littleEndian));
diff --git a/NetSharp/NetSharp/Utils/NetworkOperations.cs b/NetSharp/NetSharp/Utils/NetworkOperations.cs
@@ -3,7 +3,6 @@ using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading;
-using System.Threading.Tasks;
using NetSharp.Packets;
using NetSharp.Utils.Conversion;
@@ -12,84 +11,109 @@ namespace NetSharp.Utils
/// <summary>
/// Helper class for asynchronously performing common network operations, for both the UDP and TCP protocols.
/// </summary>
- public static class NetworkOperations
+ internal static class NetworkOperations
{
/// <summary>
- /// Reads the specified amount of data asynchronously from the network, via the given socket.
- /// The given <see cref="SocketFlags"/> are associated with the read, and the given <see cref="CancellationToken"/>
- /// is used to allow for asynchronous task cancellation.
+ /// Reads the specified amount of data from the network, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the read.
/// </summary>
/// <param name="socket">The socket which should read data from the network.</param>
/// <param name="count">The number of bytes to read from the network.</param>
/// <param name="socketFlags">The socket flags associated with the receive operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
/// <returns>The result of the receive operation.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static Task<TransmissionResult> ReadAsync(Socket socket, int count, SocketFlags socketFlags,
- CancellationToken cancellationToken)
+ private static TransmissionResult Read(Socket socket, int count, SocketFlags socketFlags)
{
- return Task.Factory.StartNew(() =>
- {
- byte[] byteBuffer = new byte[count];
- int receivedBytesCount = 0;
+ byte[] byteBuffer = new byte[count];
+ int receivedBytesCount = 0;
- while (count > receivedBytesCount)
- {
- Span<byte> receivedBytes = new Span<byte>(byteBuffer, receivedBytesCount, count - receivedBytesCount);
+ while (count > receivedBytesCount)
+ {
+ Span<byte> receivedBytes = new Span<byte>(byteBuffer, receivedBytesCount, count - receivedBytesCount);
- receivedBytesCount += socket.Receive(receivedBytes, socketFlags);
- }
+ receivedBytesCount += socket.Receive(receivedBytes, socketFlags);
+ }
- return new TransmissionResult(byteBuffer, receivedBytesCount, socket.RemoteEndPoint);
- }, cancellationToken);
+ return new TransmissionResult(byteBuffer, receivedBytesCount, socket.RemoteEndPoint); ;
}
/// <summary>
- /// Reads a datagram asynchronously from the given remote endpoint, via the given socket.
- /// The given <see cref="SocketFlags"/> are associated with the read, and the given <see cref="CancellationToken"/>
- /// is used to allow for asynchronous task cancellation.
+ /// Reads a datagram segment of the given length from the given remote endpoint, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the read.
/// </summary>
/// <param name="socket">The socket which should read data from the network.</param>
/// <param name="count">The number of bytes to read from the network.</param>
/// <param name="remoteEndPoint">The remote endpoint from which data should be read.</param>
/// <param name="socketFlags">The socket flags associated with the receive operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
/// <returns>The result of the receive operation.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static Task<TransmissionResult> ReadFromAsync(Socket socket, int count, EndPoint remoteEndPoint,
- SocketFlags socketFlags, CancellationToken cancellationToken)
+ private static TransmissionResult ReadFrom(Socket socket, int count, EndPoint remoteEndPoint, SocketFlags socketFlags)
{
- return Task.Factory.StartNew(() =>
+ byte[] byteBuffer = new byte[count];
+ EndPoint actualRemoteEndPoint = remoteEndPoint;
+ int receivedBytesCount = 0;
+
+ while (count > receivedBytesCount)
{
- byte[] byteBuffer = new byte[count];
- EndPoint actualRemoteEndPoint = remoteEndPoint;
- int receivedBytesCount = 0;
+ receivedBytesCount +=
+ socket.ReceiveMessageFrom(byteBuffer, receivedBytesCount, count - receivedBytesCount,
+ ref socketFlags, ref actualRemoteEndPoint, out IPPacketInformation _);
+ }
+
+ return new TransmissionResult(byteBuffer, receivedBytesCount, actualRemoteEndPoint);
+ }
- while (count > receivedBytesCount)
- {
- IPPacketInformation _;
+ /// <summary>
+ /// Writes the given data buffer to the network, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the write, and the given <see cref="CancellationToken"/>
+ /// is used to allow for asynchronous task cancellation.
+ /// </summary>
+ /// <param name="socket">The socket which should write data to the network.</param>
+ /// <param name="buffer">The buffer that should be written to the network.</param>
+ /// <param name="socketFlags">The socket flags associated with the send operation.</param>
+ private static void Write(Socket socket, ReadOnlyMemory<byte> buffer, SocketFlags socketFlags)
+ {
+ int bytesToSend = buffer.Length;
+ int sentBytesCount = 0;
- receivedBytesCount += socket.ReceiveMessageFrom(byteBuffer, receivedBytesCount,
- count - receivedBytesCount, ref socketFlags, ref actualRemoteEndPoint, out _);
- }
+ while (bytesToSend > sentBytesCount)
+ {
+ ReadOnlySpan<byte> bufferSegment = buffer.Span.Slice(sentBytesCount, bytesToSend - sentBytesCount);
- return new TransmissionResult(byteBuffer, receivedBytesCount, actualRemoteEndPoint);
- }, cancellationToken);
+ sentBytesCount += socket.Send(bufferSegment, socketFlags);
+ }
}
/// <summary>
- /// Reads a packet asynchronously from network, via the given socket. The given <see cref="SocketFlags"/> are
- /// associated with the read, and the given <see cref="CancellationToken"/> is used to allow for asynchronous
- /// task cancellation.
+ /// Writes the given data buffer to the given remote endpoint, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the write, and the given <see cref="CancellationToken"/>
+ /// is used to allow for asynchronous task cancellation.
+ /// </summary>
+ /// <param name="socket">The socket which should write data to the network.</param>
+ /// <param name="remoteEndPoint">The remote endpoint to which data should be written.</param>
+ /// <param name="buffer">The buffer that should be written to the network.</param>
+ /// <param name="socketFlags">The socket flags associated with the send operation.</param>
+ private static void WriteTo(Socket socket, EndPoint remoteEndPoint, ReadOnlyMemory<byte> buffer, SocketFlags socketFlags)
+ {
+ int bytesToSend = buffer.Length;
+ int sentBytesCount = 0;
+
+ while (bytesToSend > sentBytesCount)
+ {
+ ReadOnlySpan<byte> bufferSegment = buffer.Span.Slice(sentBytesCount, bytesToSend - sentBytesCount);
+
+ sentBytesCount += socket.SendTo(bufferSegment.ToArray(), socketFlags, remoteEndPoint);
+ }
+ }
+
+ /// <summary>
+ /// Reads a packet from network, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the read.
/// </summary>
/// <param name="socket">The socket which should read the packet from the network.</param>
/// <param name="socketFlags">The socket flags associated with the receive operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
/// <returns>The read packet.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static async Task<Packet> ReadPacketAsync(Socket socket, SocketFlags socketFlags, CancellationToken cancellationToken)
+ internal static Packet ReadPacket(Socket socket, SocketFlags socketFlags)
{
- TransmissionResult packetHeaderResult = await ReadAsync(socket, Packet.HeaderSize, socketFlags, cancellationToken);
+ TransmissionResult packetHeaderResult = Read(socket, Packet.HeaderSize, socketFlags);
int packetSize = EndianAwareBitConverter.ToInt32(packetHeaderResult.Buffer.Span.Slice(0, sizeof(int)));
@@ -98,7 +122,7 @@ namespace NetSharp.Utils
return Packet.Deserialise(packetHeaderResult.Buffer);
}
- TransmissionResult packetDataResult = await ReadAsync(socket, packetSize, socketFlags, cancellationToken);
+ TransmissionResult packetDataResult = Read(socket, packetSize, socketFlags);
byte[] serialisedPacket = new byte[Packet.HeaderSize + packetSize];
@@ -112,21 +136,18 @@ namespace NetSharp.Utils
}
/// <summary>
- /// Reads a packet asynchronously from the given remote endpoint, via the given socket. The given
- /// <see cref="SocketFlags"/> are associated with the read, and the given <see cref="CancellationToken"/> is
- /// used to allow for asynchronous task cancellation.
+ /// Reads a packet from the given remote endpoint, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the read.
/// </summary>
/// <param name="socket">The socket which should read the packet from the network.</param>
/// <param name="remoteEndPoint">The remote endpoint from which a packet should be read.</param>
/// <param name="socketFlags">The socket flags associated with the receive operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
/// <returns>The read packet and associated transmission results.</returns>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static async Task<(Packet packet, TransmissionResult packetResult)> ReadPacketFromAsync(
- Socket socket, EndPoint remoteEndPoint, SocketFlags socketFlags, CancellationToken cancellationToken)
+ internal static (Packet packet, TransmissionResult packetResult) ReadPacketFrom(
+ Socket socket, EndPoint remoteEndPoint, SocketFlags socketFlags)
{
TransmissionResult packetHeaderResult =
- await ReadFromAsync(socket, Packet.HeaderSize, remoteEndPoint, socketFlags, cancellationToken);
+ ReadFrom(socket, Packet.HeaderSize, remoteEndPoint, socketFlags);
int packetSize = EndianAwareBitConverter.ToInt32(packetHeaderResult.Buffer.Span.Slice(0, sizeof(int)));
@@ -136,7 +157,7 @@ namespace NetSharp.Utils
}
TransmissionResult packetDataResult =
- await ReadFromAsync(socket, packetSize, packetHeaderResult.RemoteEndPoint, socketFlags, cancellationToken);
+ ReadFrom(socket, packetSize, packetHeaderResult.RemoteEndPoint, socketFlags);
byte[] serialisedPacket = new byte[Packet.HeaderSize + packetSize];
@@ -150,87 +171,24 @@ namespace NetSharp.Utils
}
/// <summary>
- /// Writes the given buffer asynchronously to the network, via the given socket.
- /// The given <see cref="SocketFlags"/> are associated with the write, and the given <see cref="CancellationToken"/>
- /// is used to allow for asynchronous task cancellation.
- /// </summary>
- /// <param name="socket">The socket which should write data to the network.</param>
- /// <param name="buffer">The buffer that should be written to the network.</param>
- /// <param name="socketFlags">The socket flags associated with the send operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static Task WriteAsync(Socket socket, ReadOnlyMemory<byte> buffer, SocketFlags socketFlags,
- CancellationToken cancellationToken)
- {
- return Task.Factory.StartNew(() =>
- {
- int bytesToSend = buffer.Length;
- int sentBytesCount = 0;
-
- while (bytesToSend > sentBytesCount)
- {
- ReadOnlySpan<byte> bufferSegment = buffer.Span.Slice(sentBytesCount, bytesToSend - sentBytesCount);
-
- sentBytesCount += socket.Send(bufferSegment, socketFlags);
- }
- }, cancellationToken);
- }
-
- /// <summary>
- /// Writes the given packet asynchronously to the network, via the given socket. The given <see cref="SocketFlags"/>
- /// are associated with the write, and the given <see cref="CancellationToken"/> is used to allow for asynchronous
- /// task cancellation.
+ /// Writes the given packet to the network, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the write.
/// </summary>
/// <param name="socket">The socket which should write data to the network.</param>
/// <param name="packet">The packet that should be written to the network.</param>
/// <param name="socketFlags">The socket flags associated with the send operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Task WritePacketAsync(Socket socket, Packet packet, SocketFlags socketFlags,
- CancellationToken cancellationToken)
- => WriteAsync(socket, Packet.Serialise(packet), socketFlags, cancellationToken);
+ internal static void WritePacket(Socket socket, Packet packet, SocketFlags socketFlags)
+ => Write(socket, Packet.Serialise(packet), socketFlags);
/// <summary>
- /// Writes the given packet asynchronously to the given remote endpoint, via the given socket.
- /// The given <see cref="SocketFlags"/> are associated with the write, and the given <see cref="CancellationToken"/>
- /// is used to allow for asynchronous task cancellation.
+ /// Writes the given packet to the given remote endpoint, via the given socket.
+ /// The given <see cref="SocketFlags"/> are associated with the write.
/// </summary>
/// <param name="socket">The socket which should write data to the network.</param>
/// <param name="remoteEndPoint">The remote endpoint to which data should be written.</param>
/// <param name="packet">The packet that should be written to the remote endpoint.</param>
/// <param name="socketFlags">The socket flags associated with the send operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Task WritePacketToAsync(Socket socket, EndPoint remoteEndPoint, Packet packet,
- SocketFlags socketFlags, CancellationToken cancellationToken)
- => WriteToAsync(socket, remoteEndPoint, Packet.Serialise(packet), socketFlags, cancellationToken);
-
- /// <summary>
- /// Writes the given buffer asynchronously to the given remote endpoint, via the given socket.
- /// The given <see cref="SocketFlags"/> are associated with the write, and the given <see cref="CancellationToken"/>
- /// is used to allow for asynchronous task cancellation.
- /// </summary>
- /// <param name="socket">The socket which should write data to the network.</param>
- /// <param name="remoteEndPoint">The remote endpoint to which data should be written.</param>
- /// <param name="buffer">The buffer that should be written to the network.</param>
- /// <param name="socketFlags">The socket flags associated with the send operation.</param>
- /// <param name="cancellationToken">The cancellation token to use for asynchronous cancellation.</param>
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static Task WriteToAsync(Socket socket, EndPoint remoteEndPoint, ReadOnlyMemory<byte> buffer,
- SocketFlags socketFlags, CancellationToken cancellationToken)
- {
- return Task.Factory.StartNew(() =>
- {
- int bytesToSend = buffer.Length;
- int sentBytesCount = 0;
-
- while (bytesToSend > sentBytesCount)
- {
- ReadOnlySpan<byte> bufferSegment = buffer.Span.Slice(sentBytesCount, bytesToSend - sentBytesCount);
-
- sentBytesCount += socket.SendTo(bufferSegment.ToArray(), socketFlags, remoteEndPoint);
- }
- }, cancellationToken);
- }
+ internal static void WritePacketTo(Socket socket, EndPoint remoteEndPoint, Packet packet, SocketFlags socketFlags)
+ => WriteTo(socket, remoteEndPoint, Packet.Serialise(packet), socketFlags);
}
}
\ No newline at end of file
diff --git a/NetSharp/NetSharpExamples/Program.cs b/NetSharp/NetSharpExamples/Program.cs
@@ -15,12 +15,11 @@ namespace NetSharpExamples
{
internal class Program
{
+ private static int newtorkTimeout = 10;
private static IPAddress serverAddress;
private static int serverPort;
- private static int newtorkTimeout = 1_000_000;
-
private static async Task Main()
{
Console.WriteLine("Hello World!");
@@ -61,7 +60,7 @@ namespace NetSharpExamples
{
TimeSpan socketTimeout = TimeSpan.FromSeconds(newtorkTimeout);
- const int clientCount = 1;
+ const int clientCount = 10;
const int sentPacketCount = 1_000_000;
static Client ClientFactory()
@@ -134,7 +133,7 @@ namespace NetSharpExamples
{
Console.WriteLine("Socket could not be bound");
}
- }, TaskCreationOptions.LongRunning).Result;
+ }, TaskCreationOptions.LongRunning);
}
Console.ReadLine();