commit 98b1736ce0dc86bf8b7ae43518050fd53b802034
parent 874aeca6a67305adeaf6c300834be3e2f88a42bd
Author: Mikolaj Lenczewski <mikolaj.lenczewski308@gmail.com>
Date: Wed, 22 Apr 2020 22:47:53 +0100
Cleaned solution with CodeMaid, and added a tcp server benchmark and server usage examples.
Diffstat:
11 files changed, 356 insertions(+), 348 deletions(-)
diff --git a/NetSharp/NetSharp/NetSharp.xml b/NetSharp/NetSharp/NetSharp.xml
@@ -6,13 +6,13 @@
<members>
<member name="M:NetSharp.Packets.NetworkPacket.#ctor(NetSharp.Packets.NetworkPacketHeader,System.ReadOnlyMemory{System.Byte},NetSharp.Packets.NetworkPacketFooter)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Packets.NetworkPacket"/> struct.
+ Constructs a new instance of the <see cref="T:NetSharp.Packets.NetworkPacket" /> struct.
</summary>
<param name="packetHeader">The header for this packet.</param>
<param name="packetDataBuffer">The data that should be stored in the packet.</param>
<param name="packetFooter">The footer for this packet.</param>
<exception cref="T:System.ArgumentException">
- Thrown when the given <paramref name="packetDataBuffer"/> exceeds <see cref="F:NetSharp.Packets.NetworkPacket.TotalSize"/> bytes in size.
+ Thrown when the given <paramref name="packetDataBuffer" /> exceeds <see cref="F:NetSharp.Packets.NetworkPacket.TotalSize" /> bytes in size.
</exception>
</member>
<member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.CreateTransmissionArgs">
@@ -32,7 +32,7 @@
</member>
<member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.#ctor(System.Net.Sockets.AddressFamily@,System.Net.Sockets.ProtocolType@,NetSharp.Sockets.SocketServerPacketHandler@,System.Nullable{NetSharp.Sockets.Datagram.DatagramSocketServerOptions}@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.Datagram.DatagramSocketServer"/> class.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.Datagram.DatagramSocketServer" /> class.
</summary>
<param name="serverOptions">Additional options to configure the server.</param>
<inheritdoc />
@@ -67,17 +67,17 @@
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.CompletionSource">
<summary>
- The completion source which wraps the event-based APM, and provides an awaitable <see cref="T:System.Threading.Tasks.Task"/>.
+ The completion source which wraps the event-based APM, and provides an awaitable <see cref="T:System.Threading.Tasks.Task" />.
</summary>
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.CancellationToken">
<summary>
- The <see cref="T:System.Threading.CancellationToken"/> associated with the network IO operation.
+ The <see cref="T:System.Threading.CancellationToken" /> associated with the network IO operation.
</summary>
</member>
<member name="M:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.#ctor(System.Threading.Tasks.TaskCompletionSource{NetSharp.Utils.TransmissionResult}@,System.Threading.CancellationToken@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncTransmissionToken"/> struct.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncTransmissionToken" /> struct.
</summary>
<param name="completionSource">The completion source to trigger when the IO operation completes.</param>
<param name="cancellationToken">The cancellation token to observe during the operation.</param>
@@ -89,17 +89,17 @@
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncOperationToken.CompletionSource">
<summary>
- The completion source which wraps the event-based APM, and provides an awaitable <see cref="T:System.Threading.Tasks.Task"/>.
+ The completion source which wraps the event-based APM, and provides an awaitable <see cref="T:System.Threading.Tasks.Task" />.
</summary>
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncOperationToken.CancellationToken">
<summary>
- The <see cref="T:System.Threading.CancellationToken"/> associated with the socket operation.
+ The <see cref="T:System.Threading.CancellationToken" /> associated with the socket operation.
</summary>
</member>
<member name="M:NetSharp.Sockets.SocketClient.AsyncOperationToken.#ctor(System.Threading.Tasks.TaskCompletionSource{System.Boolean}@,System.Threading.CancellationToken@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncOperationToken"/> struct.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncOperationToken" /> struct.
</summary>
<param name="completionSource">The completion source to trigger when the socket operation completes.</param>
<param name="cancellationToken">The cancellation token to observe during the operation.</param>
@@ -116,12 +116,12 @@
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.TransmissionArgs">
<summary>
- The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instance associated with the network IO operation.
+ The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance associated with the network IO operation.
</summary>
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.TransmissionArgsPool">
<summary>
- The pool to which the <see cref="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.TransmissionArgs"/> should be returned upon operation cancellation.
+ The pool to which the <see cref="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.TransmissionArgs" /> should be returned upon operation cancellation.
</summary>
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.CompletionSource">
@@ -131,11 +131,11 @@
</member>
<member name="M:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.#ctor(System.Net.Sockets.Socket@,System.Net.Sockets.SocketAsyncEventArgs@,NetSharp.Utils.SlimObjectPool{System.Net.Sockets.SocketAsyncEventArgs}@,System.Threading.Tasks.TaskCompletionSource{NetSharp.Utils.TransmissionResult}@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken"/> struct.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken" /> struct.
</summary>
<param name="socket">The socket on which the operation was started.</param>
<param name="args">The socket event args associated with the operation.</param>
- <param name="argsPool">The pool to which the <paramref name="args"/> instance will be returned upon cancellation.</param>
+ <param name="argsPool">The pool to which the <paramref name="args" /> instance will be returned upon cancellation.</param>
<param name="completionSource">The completion source associated with the operation.</param>
</member>
<member name="T:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken">
@@ -150,12 +150,12 @@
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgs">
<summary>
- The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instance associated with the socket operation.
+ The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance associated with the socket operation.
</summary>
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgsPool">
<summary>
- The pool to which the <see cref="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgs"/> should be returned upon operation cancellation.
+ The pool to which the <see cref="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgs" /> should be returned upon operation cancellation.
</summary>
</member>
<member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.CompletionSource">
@@ -165,16 +165,16 @@
</member>
<member name="M:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.#ctor(System.Net.Sockets.Socket@,System.Net.Sockets.SocketAsyncEventArgs@,NetSharp.Utils.SlimObjectPool{System.Net.Sockets.SocketAsyncEventArgs}@,System.Threading.Tasks.TaskCompletionSource{System.Boolean}@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken"/> struct.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken" /> struct.
</summary>
<param name="socket">The socket on which the operation was started.</param>
<param name="args">The socket event args associated with the operation.</param>
- <param name="argsPool">The pool to which the <paramref name="args"/> instance will be returned upon cancellation.</param>
+ <param name="argsPool">The pool to which the <paramref name="args" /> instance will be returned upon cancellation.</param>
<param name="completionSource">The completion source associated with the operation.</param>
</member>
<member name="M:NetSharp.Sockets.SocketClient.#ctor(System.Net.Sockets.AddressFamily@,System.Net.Sockets.SocketType@,System.Net.Sockets.ProtocolType@,System.Int32@,System.UInt16@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient"/> class.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient" /> class.
</summary>
<param name="connectionAddressFamily">The address family that the underlying connection should use.</param>
<param name="connectionSocketType">The socket type that the underlying connection should use.</param>
@@ -184,23 +184,23 @@
</member>
<member name="M:NetSharp.Sockets.SocketClient.Connect(System.Net.EndPoint@)">
<summary>
- Connects the client to the specified end point. If called on a <see cref="F:System.Net.Sockets.SocketType.Dgram"/>-based client,
+ Connects the client to the specified end point. If called on a <see cref="F:System.Net.Sockets.SocketType.Dgram" />-based client,
this method configures the default remote host, and the client will ignore any packets not coming from this
- default host (i.e the given <paramref name="remoteEndPoint"/>).
+ default host (i.e the given <paramref name="remoteEndPoint" />).
</summary>
<param name="remoteEndPoint">The remote end point which to which to connect the client.</param>
</member>
<member name="M:NetSharp.Sockets.SocketClient.ConnectAsync(System.Net.EndPoint@,System.Threading.CancellationToken)">
<summary>
Asynchronously connects the client to the specified end point. If called on a
- <see cref="F:System.Net.Sockets.SocketType.Dgram"/>-based client, this method configures the default remote host, and the client
- will ignore any packets not coming from this default host (i.e the given <paramref name="remoteEndPoint"/>).
+ <see cref="F:System.Net.Sockets.SocketType.Dgram" />-based client, this method configures the default remote host, and the client
+ will ignore any packets not coming from this default host (i.e the given <paramref name="remoteEndPoint" />).
</summary>
<param name="remoteEndPoint">The remote end point which to which to connect the client.</param>
<param name="cancellationToken">
- The <see cref="T:System.Threading.CancellationToken"/> upon whose cancellation the connection attempt should be aborted.
+ The <see cref="T:System.Threading.CancellationToken" /> upon whose cancellation the connection attempt should be aborted.
</param>
- <returns>A <see cref="T:System.Threading.Tasks.ValueTask"/> representing the connection attempt.</returns>
+ <returns>A <see cref="T:System.Threading.Tasks.ValueTask" /> representing the connection attempt.</returns>
</member>
<member name="T:NetSharp.Sockets.SocketConnection">
<summary>
@@ -210,7 +210,7 @@
</member>
<member name="F:NetSharp.Sockets.SocketConnection.Connection">
<summary>
- The underlying <see cref="T:System.Net.Sockets.Socket"/> which provides access to network operations.
+ The underlying <see cref="T:System.Net.Sockets.Socket" /> which provides access to network operations.
</summary>
</member>
<member name="F:NetSharp.Sockets.SocketConnection.BufferPool">
@@ -220,58 +220,58 @@
</member>
<member name="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool">
<summary>
- Pools <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> objects for use during network read/write operations and calls
- to <see cref="T:System.Net.Sockets.Socket"/>.XXXAsync(<see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/>) methods.
+ Pools <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> objects for use during network read/write operations and calls
+ to <see cref="T:System.Net.Sockets.Socket" />.XXXAsync(<see cref="T:System.Net.Sockets.SocketAsyncEventArgs" />) methods.
</summary>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.#ctor(System.Net.Sockets.AddressFamily@,System.Net.Sockets.SocketType@,System.Net.Sockets.ProtocolType@,System.Int32@,System.UInt16@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketConnection"/> class.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketConnection" /> class.
</summary>
<param name="connectionAddressFamily">The address family for the underlying socket.</param>
<param name="connectionSocketType">The socket type for the underlying socket.</param>
<param name="connectionProtocolType">The protocol type for the underlying socket.</param>
- <param name="maxPooledBufferLength">The maximum size of the buffers stored in the <see cref="F:NetSharp.Sockets.SocketConnection.BufferPool"/>.</param>
- <param name="preallocatedTransmissionArgs"> The number of <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> objects to initially preallocate.</param>
+ <param name="maxPooledBufferLength">The maximum size of the buffers stored in the <see cref="F:NetSharp.Sockets.SocketConnection.BufferPool" />.</param>
+ <param name="preallocatedTransmissionArgs"> The number of <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> objects to initially preallocate.</param>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.CreateTransmissionArgs">
<summary>
- Delegate method used to construct fresh <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instances for use in the
- <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool"/>. The resulting instance should register <see cref="M:NetSharp.Sockets.SocketConnection.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"/>
- as an event handler for the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed"/> event.
+ Delegate method used to construct fresh <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instances for use in the
+ <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool" />. The resulting instance should register <see cref="M:NetSharp.Sockets.SocketConnection.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)" />
+ as an event handler for the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event.
</summary>
- <returns>The configured <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instance.</returns>
+ <returns>The configured <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance.</returns>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)">
<summary>
- Delegate method used to reset used <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instances for later reuse by
- the <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool"/>.
+ Delegate method used to reset used <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instances for later reuse by
+ the <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool" />.
</summary>
- <param name="args">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instance that should be reset.</param>
+ <param name="args">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance that should be reset.</param>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)">
<summary>
- Delegate method used to check whether the given used <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instance can be reused
- by the <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool"/>. If this method returns <c>true</c>, <see cref="M:NetSharp.Sockets.SocketConnection.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"/>
- is called on the given <paramref name="args"/>. Otherwise, <see cref="M:NetSharp.Sockets.SocketConnection.DestroyTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"/> is called.
+ Delegate method used to check whether the given used <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance can be reused
+ by the <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool" />. If this method returns <c>true</c>, <see cref="M:NetSharp.Sockets.SocketConnection.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)" />
+ is called on the given <paramref name="args" />. Otherwise, <see cref="M:NetSharp.Sockets.SocketConnection.DestroyTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)" /> is called.
</summary>
- <param name="args">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instance to check.</param>
- <returns>Whether the given <paramref name="args"/> should be reset and reused, or should be destroyed.</returns>
+ <param name="args">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance to check.</param>
+ <returns>Whether the given <paramref name="args" /> should be reset and reused, or should be destroyed.</returns>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.DestroyTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)">
<summary>
- Delegate method to destroy used <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instances that cannot be reused by the
- <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool"/>. This method should deregister <see cref="M:NetSharp.Sockets.SocketConnection.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"/> as an
- event handler for the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed"/> event.
+ Delegate method to destroy used <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instances that cannot be reused by the
+ <see cref="F:NetSharp.Sockets.SocketConnection.TransmissionArgsPool" />. This method should deregister <see cref="M:NetSharp.Sockets.SocketConnection.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)" /> as an
+ event handler for the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event.
</summary>
- <param name="remoteConnectionArgs">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> which should be destroyed.</param>
+ <param name="remoteConnectionArgs">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> which should be destroyed.</param>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)">
<summary>
- Delegate method to handle asynchronous network IO completion via the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed"/> event.
+ Delegate method to handle asynchronous network IO completion via the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event.
</summary>
<param name="sender">The object which raised the event.</param>
- <param name="args">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs"/> instance associated with the asynchronous network IO.</param>
+ <param name="args">The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance associated with the asynchronous network IO.</param>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.Bind(System.Net.EndPoint@)">
<summary>
@@ -287,9 +287,9 @@
</member>
<member name="M:NetSharp.Sockets.SocketConnection.Dispose(System.Boolean)">
<summary>
- Disposes of managed and unmanaged resources used by the <see cref="T:NetSharp.Sockets.SocketConnection"/> class.
+ Disposes of managed and unmanaged resources used by the <see cref="T:NetSharp.Sockets.SocketConnection" /> class.
</summary>
- <param name="disposing">Whether this call was made by a call to <see cref="M:NetSharp.Sockets.SocketConnection.Dispose"/>.</param>
+ <param name="disposing">Whether this call was made by a call to <see cref="M:NetSharp.Sockets.SocketConnection.Dispose" />.</param>
</member>
<member name="M:NetSharp.Sockets.SocketConnection.Dispose">
<inheritdoc />
@@ -302,7 +302,7 @@
<param name="clientEndPoint">The client from which the packet was received.</param>
<returns>
The response packet which should be sent out to the client. If no packet should be sent out,
- this method must return <see cref="F:NetSharp.Packets.NetworkPacket.NullPacket"/>.
+ this method must return <see cref="F:NetSharp.Packets.NetworkPacket.NullPacket" />.
</returns>
</member>
<member name="T:NetSharp.Sockets.SocketServer">
@@ -317,7 +317,7 @@
</member>
<member name="M:NetSharp.Sockets.SocketServer.#ctor(System.Net.Sockets.AddressFamily@,System.Net.Sockets.SocketType@,System.Net.Sockets.ProtocolType@,NetSharp.Sockets.SocketServerPacketHandler@,System.Int32@,System.UInt16@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketServer"/> class.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketServer" /> class.
</summary>
<param name="connectionAddressFamily">The address family that the underlying connection should use.</param>
<param name="connectionSocketType">The socket type that the underlying connection should use.</param>
@@ -336,10 +336,10 @@
</member>
<member name="M:NetSharp.Sockets.SocketServer.RunAsync(System.Threading.CancellationToken)">
<summary>
- Runs the server, handling requests from clients, until the <paramref name="cancellationToken"/> has its cancellation requested.
+ Runs the server, handling requests from clients, until the <paramref name="cancellationToken" /> has its cancellation requested.
</summary>
- <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken"/> upon whose cancellation the server should shut down.</param>
- <returns>A <see cref="T:System.Threading.Tasks.Task"/> representing the server's execution.</returns>
+ <param name="cancellationToken">The <see cref="T:System.Threading.CancellationToken" /> upon whose cancellation the server should shut down.</param>
+ <returns>A <see cref="T:System.Threading.Tasks.Task" /> representing the server's execution.</returns>
</member>
<member name="M:NetSharp.Sockets.Stream.StreamSocketClient.CreateTransmissionArgs">
<inheritdoc />
@@ -358,7 +358,7 @@
</member>
<member name="M:NetSharp.Sockets.Stream.StreamSocketServer.#ctor(System.Net.Sockets.AddressFamily@,System.Net.Sockets.ProtocolType@,NetSharp.Sockets.SocketServerPacketHandler@,System.Nullable{NetSharp.Sockets.Stream.StreamSocketServerOptions}@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Sockets.Stream.StreamSocketServer"/> class.
+ Constructs a new instance of the <see cref="T:NetSharp.Sockets.Stream.StreamSocketServer" /> class.
</summary>
<param name="serverOptions">Additional options to configure the server.</param>
<inheritdoc />
@@ -400,7 +400,7 @@
</member>
<member name="M:NetSharp.Utils.BiDictionary`2.#ctor">
<summary>
- Initialises a new instance of the <see cref="T:NetSharp.Utils.BiDictionary`2"/> class.
+ Initialises a new instance of the <see cref="T:NetSharp.Utils.BiDictionary`2" /> class.
</summary>
</member>
<member name="P:NetSharp.Utils.BiDictionary`2.Item(`1)">
@@ -419,7 +419,7 @@
</member>
<member name="M:NetSharp.Utils.BiDictionary`2.Clear">
<summary>
- Clears this instance's <see cref="F:NetSharp.Utils.BiDictionary`2.keyToValueMap"/> and <see cref="F:NetSharp.Utils.BiDictionary`2.valueToKeyMap"/>.
+ Clears this instance's <see cref="F:NetSharp.Utils.BiDictionary`2.keyToValueMap" /> and <see cref="F:NetSharp.Utils.BiDictionary`2.valueToKeyMap" />.
</summary>
</member>
<member name="M:NetSharp.Utils.BiDictionary`2.ContainsKey(`0@)">
@@ -502,7 +502,7 @@
</member>
<member name="T:NetSharp.Utils.Conversion.EndianAwareBitConverter">
<summary>
- Wraps the <see cref="T:System.BitConverter"/> class to provide conversion that is endian-aware.
+ Wraps the <see cref="T:System.BitConverter" /> class to provide conversion that is endian-aware.
</summary>
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ReverseAsNeeded(System.Span{System.Byte},System.Boolean)">
@@ -511,64 +511,64 @@
</summary>
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.Boolean,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.Boolean)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.Boolean)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.Char,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.Char)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.Char)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.Double,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.Double)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.Double)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.Single,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.Single)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.Single)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.Int32,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.Int32)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.Int32)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.Int64,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.Int64)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.Int64)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.Int16,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.Int16)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.Int16)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.UInt32,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.UInt32)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.UInt32)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.UInt64,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.UInt64)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.UInt64)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.GetBytes(System.UInt16,System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.GetBytes(System.UInt16)"/>
+ <inheritdoc cref="M:System.BitConverter.GetBytes(System.UInt16)" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToBoolean(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToBoolean(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToBoolean(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToChar(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToChar(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToChar(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToDouble(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToDouble(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToDouble(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToInt16(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToInt16(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToInt16(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToInt32(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToInt32(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToInt32(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToInt64(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToInt64(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToInt64(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToSingle(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToSingle(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToSingle(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToUInt16(System.Byte[],System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToUInt16(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToUInt16(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToUInt32(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToUInt32(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToUInt32(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="M:NetSharp.Utils.Conversion.EndianAwareBitConverter.ToUInt64(System.Span{System.Byte},System.Boolean)">
- <inheritdoc cref="M:System.BitConverter.ToUInt64(System.ReadOnlySpan{System.Byte})"/>
+ <inheritdoc cref="M:System.BitConverter.ToUInt64(System.ReadOnlySpan{System.Byte})" />
</member>
<member name="T:NetSharp.Utils.SlimObjectPool`1">
<summary>
@@ -578,14 +578,14 @@
</member>
<member name="T:NetSharp.Utils.SlimObjectPool`1.CreateObjectDelegate">
<summary>
- Delegate method for creating fresh <typeparamref name="T"/> instances to be stored in the pool.
+ Delegate method for creating fresh <typeparamref name="T" /> instances to be stored in the pool.
</summary>
- <returns>A configured <typeparamref name="T"/> instance.</returns>
+ <returns>A configured <typeparamref name="T" /> instance.</returns>
</member>
<member name="T:NetSharp.Utils.SlimObjectPool`1.CanRebufferObjectPredicate">
<summary>
- Delegate method to check whether the given <paramref name="instance"/> can and should be placed
- back into the pool. If <c>true</c> is returned, the <paramref name="instance"/> is reset and placed
+ Delegate method to check whether the given <paramref name="instance" /> can and should be placed
+ back into the pool. If <c>true</c> is returned, the <paramref name="instance" /> is reset and placed
back into the pool. Otherwise, the instance is destroyed.
</summary>
<param name="instance">The instance to check.</param>
@@ -593,19 +593,19 @@
</member>
<member name="T:NetSharp.Utils.SlimObjectPool`1.ResetObjectDelegate">
<summary>
- Delegate method to reset a used <paramref name="instance"/> before placing it back into the pool.
+ Delegate method to reset a used <paramref name="instance" /> before placing it back into the pool.
</summary>
<param name="instance">The instance which should be reset.</param>
</member>
<member name="T:NetSharp.Utils.SlimObjectPool`1.DestroyObjectDelegate">
<summary>
- Delegate method to destroy a used <paramref name="instance"/> which cannot be reused.
+ Delegate method to destroy a used <paramref name="instance" /> which cannot be reused.
</summary>
<param name="instance">The instance to destroy.</param>
</member>
<member name="M:NetSharp.Utils.SlimObjectPool`1.#ctor(NetSharp.Utils.SlimObjectPool{`0}.CreateObjectDelegate@,NetSharp.Utils.SlimObjectPool{`0}.ResetObjectDelegate@,NetSharp.Utils.SlimObjectPool{`0}.DestroyObjectDelegate@,NetSharp.Utils.SlimObjectPool{`0}.CanRebufferObjectPredicate@,System.Collections.Concurrent.IProducerConsumerCollection{`0}@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1"/> class.
+ Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1" /> class.
</summary>
<param name="createDelegate">The delegate method to use to create new pooled object instances.</param>
<param name="resetDelegate">The delegate method to use to reset used pooled object instances.</param>
@@ -615,7 +615,7 @@
</member>
<member name="M:NetSharp.Utils.SlimObjectPool`1.#ctor(NetSharp.Utils.SlimObjectPool{`0}.CreateObjectDelegate@,NetSharp.Utils.SlimObjectPool{`0}.ResetObjectDelegate@,NetSharp.Utils.SlimObjectPool{`0}.DestroyObjectDelegate@,NetSharp.Utils.SlimObjectPool{`0}.CanRebufferObjectPredicate@)">
<summary>
- Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1"/> class.
+ Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1" /> class.
</summary>
<param name="createDelegate">The delegate method to use to create new pooled object instances.</param>
<param name="resetDelegate">The delegate method to use to reset used pooled object instances.</param>
@@ -624,13 +624,13 @@
</member>
<member name="M:NetSharp.Utils.SlimObjectPool`1.Rent">
<summary>
- Leases a new <typeparamref name="T"/> instance from the pool, and returns it.
+ Leases a new <typeparamref name="T" /> instance from the pool, and returns it.
</summary>
- <returns>The <typeparamref name="T"/> instance which was fetched from the pool.</returns>
+ <returns>The <typeparamref name="T" /> instance which was fetched from the pool.</returns>
</member>
<member name="M:NetSharp.Utils.SlimObjectPool`1.Return(`0)">
<summary>
- Returns a previously leased <typeparamref name="T"/> instance to the pool.
+ Returns a previously leased <typeparamref name="T" /> instance to the pool.
</summary>
<param name="instance">The previously leased instance which should be returned.</param>
</member>
@@ -641,13 +641,13 @@
</member>
<member name="M:NetSharp.Utils.TransmissionResult.#ctor(System.Net.Sockets.SocketAsyncEventArgs@)">
<summary>
- Initialises a new instance of the <see cref="T:NetSharp.Utils.TransmissionResult"/> struct.
+ Initialises a new instance of the <see cref="T:NetSharp.Utils.TransmissionResult" /> struct.
</summary>
<param name="args">The socket arguments associated with the transmission.</param>
</member>
<member name="M:NetSharp.Utils.TransmissionResult.#ctor(System.Byte[]@,System.Int32@,System.Net.EndPoint@)">
<summary>
- Initialises a new instance of the <see cref="T:NetSharp.Utils.TransmissionResult"/> struct.
+ Initialises a new instance of the <see cref="T:NetSharp.Utils.TransmissionResult" /> struct.
</summary>
<param name="buffer">The buffer associated with the transmission.</param>
<param name="count">The number of bytes written to or read from the buffer.</param>
@@ -669,4 +669,4 @@
</summary>
</member>
</members>
-</doc>
+</doc>
+\ No newline at end of file
diff --git a/NetSharp/NetSharp/Sockets/Datagram/DatagramSocketClient.cs b/NetSharp/NetSharp/Sockets/Datagram/DatagramSocketClient.cs
@@ -173,8 +173,7 @@ namespace NetSharp.Sockets.Datagram
cancellationToken.Register(token =>
{
AsyncTransmissionCancellationToken transmissionCancellationToken =
- (AsyncTransmissionCancellationToken) token;
-
+ (AsyncTransmissionCancellationToken)token;
}, new AsyncTransmissionCancellationToken(in Connection, in args, in TransmissionArgsPool, in tcs));
if (Connection.ReceiveFromAsync(args)) return new ValueTask<TransmissionResult>(tcs.Task);
@@ -211,7 +210,6 @@ namespace NetSharp.Sockets.Datagram
{
AsyncTransmissionCancellationToken transmissionCancellationToken =
(AsyncTransmissionCancellationToken)token;
-
}, new AsyncTransmissionCancellationToken(in Connection, in args, in TransmissionArgsPool, in tcs));
if (Connection.SendToAsync(args)) return new ValueTask<TransmissionResult>(tcs.Task);
diff --git a/NetSharp/NetSharp/Sockets/SocketClient.cs b/NetSharp/NetSharp/Sockets/SocketClient.cs
@@ -205,7 +205,7 @@ namespace NetSharp.Sockets
cancellationToken.Register(token =>
{
- AsyncOperationCancellationToken operationCancellationToken = (AsyncOperationCancellationToken) token;
+ AsyncOperationCancellationToken operationCancellationToken = (AsyncOperationCancellationToken)token;
Socket.CancelConnectAsync(operationCancellationToken.TransmissionArgs);
diff --git a/NetSharp/NetSharp/Sockets/SocketConnection.cs b/NetSharp/NetSharp/Sockets/SocketConnection.cs
@@ -47,6 +47,7 @@ namespace NetSharp.Sockets
TransmissionArgsPool = new SlimObjectPool<SocketAsyncEventArgs>(CreateTransmissionArgs,
ResetTransmissionArgs, DestroyTransmissionArgs, CanTransmissionArgsBeReused);
+ // TODO refactor into a cleaner structure, with a better method of seeding the object pool
for (ushort i = 0; i < preallocatedTransmissionArgs; i++)
{
SocketAsyncEventArgs args = CreateTransmissionArgs();
diff --git a/NetSharp/NetSharp/Sockets/SocketServer.cs b/NetSharp/NetSharp/Sockets/SocketServer.cs
@@ -1,8 +1,9 @@
-using System.Net;
+using NetSharp.Packets;
+
+using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
-using NetSharp.Packets;
namespace NetSharp.Sockets
{
diff --git a/NetSharp/NetSharpExamples/Examples/TcpSocketServerBenchmark.cs b/NetSharp/NetSharpExamples/Examples/TcpSocketServerBenchmark.cs
@@ -0,0 +1,157 @@
+using NetSharp.Packets;
+using NetSharp.Sockets;
+using NetSharp.Sockets.Stream;
+
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace NetSharpExamples.Examples
+{
+ public class TcpSocketServerBenchmark : INetSharpExample
+ {
+ private const int PacketCount = 1_000_000;
+
+ private static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12348);
+
+ private double[] ClientBandwidths;
+
+ public async Task RunAsync()
+ {
+ CancellationTokenSource serverCts = new CancellationTokenSource();
+
+ int clientCount = Environment.ProcessorCount / 2;
+
+ Console.WriteLine($"TCP Server Benchmark started!");
+
+ StreamSocketServerOptions serverOptions = new StreamSocketServerOptions(NetworkPacket.TotalSize,
+ clientCount, (ushort)clientCount);
+
+ StreamSocketServer server = new StreamSocketServer(AddressFamily.InterNetwork, ProtocolType.Tcp,
+ SocketServer.DefaultPacketHandler, serverOptions);
+
+ server.Bind(ServerEndPoint);
+
+ Task serverTask = Task.Factory.StartNew(() =>
+ {
+ server.RunAsync(serverCts.Token).GetAwaiter().GetResult();
+ }, TaskCreationOptions.LongRunning);
+
+ ClientBandwidths = new double[clientCount];
+ Task[] clientTasks = new Task[clientCount];
+ for (int i = 0; i < clientTasks.Length; i++)
+ {
+ clientTasks[i] = Task.Factory.StartNew(BenchmarkClientTask, i, TaskCreationOptions.LongRunning);
+ }
+
+ await Task.WhenAll(clientTasks);
+
+ Console.WriteLine($"Total estimated bandwidth: {ClientBandwidths.Sum():F5}");
+
+ serverCts.Cancel();
+
+ await serverTask;
+
+ Console.WriteLine($"TCP Server Benchmark finished!");
+ }
+
+ private Task BenchmarkClientTask(object idObj)
+ {
+ int id = (int)idObj;
+
+ BenchmarkHelper benchmarkHelper = new BenchmarkHelper();
+
+ Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
+
+ clientSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
+ clientSocket.Connect(ServerEndPoint);
+
+ byte[] sendBuffer = new byte[NetworkPacket.TotalSize];
+ byte[] receiveBuffer = new byte[NetworkPacket.TotalSize];
+
+ EndPoint remoteEndPoint = ServerEndPoint;
+
+ lock (typeof(Console))
+ {
+ Console.WriteLine($"[Client {id}] Starting client; sending messages to {remoteEndPoint}");
+ }
+
+ for (int i = 0; i < PacketCount; i++)
+ {
+ byte[] packetBuffer = Encoding.UTF8.GetBytes($"[Client {id}] Hello World! (Packet {i})");
+ packetBuffer.CopyTo(sendBuffer, 0);
+
+ benchmarkHelper.StartBandwidthStopwatch();
+ benchmarkHelper.StartRttStopwatch();
+
+ int totalSent = 0;
+ do
+ {
+ totalSent += clientSocket.Send(sendBuffer, totalSent, sendBuffer.Length - totalSent,
+ SocketFlags.None);
+ } while (totalSent != 0 && totalSent != sendBuffer.Length);
+
+ if (totalSent == 0)
+ {
+ break;
+ }
+
+#if DEBUG
+ lock (typeof(Console))
+ {
+ Console.WriteLine($"[Client {id}, Packet {i}] Sent {sentBytes} bytes to {remoteEndPoint}");
+ Console.WriteLine($"[Client {id}, Packet {i}] >>>> {Encoding.UTF8.GetString(sendBuffer)}");
+ }
+#endif
+
+ int totalReceived = 0;
+ do
+ {
+ totalReceived += clientSocket.Receive(receiveBuffer, totalReceived,
+ receiveBuffer.Length - totalReceived, SocketFlags.None);
+ } while (totalReceived != 0 && totalReceived != sendBuffer.Length);
+
+ if (totalReceived == 0)
+ {
+ break;
+ }
+
+ benchmarkHelper.StopRttStopwatch();
+ benchmarkHelper.StopBandwidthStopwatch();
+
+#if DEBUG
+ lock (typeof(Console))
+ {
+ Console.WriteLine($"[Client {id}, Packet {i}] Received {receivedBytes} bytes from {remoteEndPoint}");
+ Console.WriteLine($"[Client {id}, Packet {i}] <<<< {Encoding.UTF8.GetString(receiveBuffer)}");
+ }
+#endif
+
+ benchmarkHelper.UpdateRttStats(id);
+
+ /*
+ lock (typeof(Console))
+ {
+ Console.WriteLine($"[Client {id}] Current RTT: {benchmarkHelper.RttTicks} ticks, {benchmarkHelper.RttMs} ms");
+ }
+ */
+
+ benchmarkHelper.ResetRttStopwatch();
+ }
+
+ clientSocket.Disconnect(true);
+ clientSocket.Close();
+
+ benchmarkHelper.PrintBandwidthStats(id, PacketCount, NetworkPacket.TotalSize);
+ benchmarkHelper.PrintRttStats(id);
+
+ ClientBandwidths[id] = benchmarkHelper.CalcBandwidth(PacketCount, NetworkPacket.TotalSize);
+
+ return Task.CompletedTask;
+ }
+ }
+}
+\ No newline at end of file
diff --git a/NetSharp/NetSharpExamples/Examples/TcpSocketServerExample.cs b/NetSharp/NetSharpExamples/Examples/TcpSocketServerExample.cs
@@ -0,0 +1,40 @@
+using NetSharp.Packets;
+using NetSharp.Sockets.Stream;
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace NetSharpExamples.Examples
+{
+ public class TcpSocketServerExample : INetSharpExample
+ {
+ public Task RunAsync()
+ {
+ StreamSocketServerOptions serverOptions =
+ new StreamSocketServerOptions(NetworkPacket.TotalSize, Environment.ProcessorCount, 2);
+
+ using StreamSocketServer server =
+ new StreamSocketServer(AddressFamily.InterNetwork, ProtocolType.Tcp, ServerPacketHandler, serverOptions);
+
+ return server.RunAsync(CancellationToken.None); // we run forever. alternatively, pass in a cancellation token to ensure that the server terminates
+ }
+
+ public static NetworkPacket ServerPacketHandler(in NetworkPacket request, in EndPoint remoteEndPoint)
+ {
+ // lock is not necessary, but means that console output is clean and not interleaved
+ lock (typeof(Console))
+ {
+ Console.WriteLine($"[Server] Received request with contents \'{Encoding.UTF8.GetString(request.Data.Span)}\' from {remoteEndPoint}");
+ Console.WriteLine($"[Server] Echoing back request to {remoteEndPoint}");
+ }
+
+ // we echo back the request, but we could just as easily send back a new packet.
+ // if we would not want to send back any response, we need to return NetworkPacket.NullPacket
+ return request;
+ }
+ }
+}
+\ No newline at end of file
diff --git a/NetSharp/NetSharpExamples/Examples/UdpSocketServerBenchmark.cs b/NetSharp/NetSharpExamples/Examples/UdpSocketServerBenchmark.cs
@@ -1,13 +1,14 @@
-using System;
+using NetSharp.Packets;
+using NetSharp.Sockets;
+using NetSharp.Sockets.Datagram;
+
+using System;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using NetSharp.Packets;
-using NetSharp.Sockets;
-using NetSharp.Sockets.Datagram;
namespace NetSharpExamples.Examples
{
@@ -25,6 +26,8 @@ namespace NetSharpExamples.Examples
int clientCount = Environment.ProcessorCount / 2;
+ Console.WriteLine($"UDP Server Benchmark started!");
+
DatagramSocketServerOptions serverOptions = new DatagramSocketServerOptions(NetworkPacket.TotalSize,
clientCount, (ushort)clientCount);
@@ -53,17 +56,19 @@ namespace NetSharpExamples.Examples
await serverTask;
- Console.WriteLine($"Benchmark finished!");
+ Console.WriteLine($"UDP Server Benchmark finished!");
}
private Task BenchmarkClientTask(object idObj)
{
- int id = (int) idObj;
+ int id = (int)idObj;
BenchmarkHelper benchmarkHelper = new BenchmarkHelper();
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ clientSocket.Bind(new IPEndPoint(IPAddress.Any, 0));
+
byte[] sendBuffer = new byte[NetworkPacket.TotalSize];
byte[] receiveBuffer = new byte[NetworkPacket.TotalSize];
diff --git a/NetSharp/NetSharpExamples/Examples/UdpSocketServerExample.cs b/NetSharp/NetSharpExamples/Examples/UdpSocketServerExample.cs
@@ -0,0 +1,40 @@
+using NetSharp.Packets;
+using NetSharp.Sockets.Datagram;
+
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace NetSharpExamples.Examples
+{
+ public class UdpSocketServerExample : INetSharpExample
+ {
+ public Task RunAsync()
+ {
+ DatagramSocketServerOptions serverOptions =
+ new DatagramSocketServerOptions(NetworkPacket.TotalSize, Environment.ProcessorCount, 2);
+
+ using DatagramSocketServer server =
+ new DatagramSocketServer(AddressFamily.InterNetwork, ProtocolType.Udp, ServerPacketHandler, serverOptions);
+
+ return server.RunAsync(CancellationToken.None); // we run forever. alternatively, pass in a cancellation token to ensure that the server terminates
+ }
+
+ public static NetworkPacket ServerPacketHandler(in NetworkPacket request, in EndPoint remoteEndPoint)
+ {
+ // lock is not necessary, but means that console output is clean and not interleaved
+ lock (typeof(Console))
+ {
+ Console.WriteLine($"[Server] Received request with contents \'{Encoding.UTF8.GetString(request.Data.Span)}\' from {remoteEndPoint}");
+ Console.WriteLine($"[Server] Echoing back request to {remoteEndPoint}");
+ }
+
+ // we echo back the request, but we could just as easily send back a new packet.
+ // if we would not want to send back any response, we need to return NetworkPacket.NullPacket
+ return request;
+ }
+ }
+}
+\ No newline at end of file
diff --git a/NetSharp/NetSharpExamples/NetSharpExamples.xml b/NetSharp/NetSharpExamples/NetSharpExamples.xml
@@ -5,4 +5,4 @@
</assembly>
<members>
</members>
-</doc>
+</doc>
+\ No newline at end of file
diff --git a/NetSharp/NetSharpExamples/Program.cs b/NetSharp/NetSharpExamples/Program.cs
@@ -1,31 +1,12 @@
-#define TCP
-#undef TCP
-
-using NetSharp.Packets;
-using NetSharp.Sockets.Datagram;
-using NetSharp.Sockets.Stream;
-using NetSharp.Utils;
+using NetSharpExamples.Examples;
using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Net;
-using System.Net.Sockets;
-using System.Text;
using System.Threading.Tasks;
-using NetSharp.Sockets;
-using NetSharpExamples.Examples;
namespace NetSharpExamples
{
internal class Program
{
- private const int NetworkTimeout = 1_000_000;
- private const int ServerPort = 12374;
- private static readonly IPAddress ServerAddress = IPAddress.Parse("192.168.0.10");
- private static readonly EndPoint ServerEndPoint = new IPEndPoint(ServerAddress, ServerPort);
-
private static async Task Main()
{
Console.WriteLine("Hello World!");
@@ -33,230 +14,10 @@ namespace NetSharpExamples
INetSharpExample udpSocketServerBenchmark = new UdpSocketServerBenchmark();
await udpSocketServerBenchmark.RunAsync();
- /*
- Console.WriteLine("Starting socket server test...");
- Task serverTest = TestSocketServer();
-
- Console.WriteLine("Starting socket client test...");
- Task clientTest = TestSocketClient();
- await clientTest;
- */
+ INetSharpExample tcpSocketServerBenchmark = new TcpSocketServerBenchmark();
+ await tcpSocketServerBenchmark.RunAsync();
Console.ReadLine();
}
-
- #region Socket Tests
-
- private static async Task TestSocketClient()
- {
- const int clientCount = 4;
- const long packetsToSend = 100_000;
-
- Task[] clientTasks = new Task[clientCount];
- double[] clientBandwidths = new double[clientCount];
- HashSet<int> activeTasks = new HashSet<int>(clientCount);
-
- async Task ClientTask(object id)
- {
- try
- {
- lock (typeof(Console))
- {
- Console.WriteLine($"[Client {id}] Starting client...");
- }
-
-#if TCP
- using StreamSocketClient client = new StreamSocketClient(AddressFamily.InterNetwork, ProtocolType.Tcp);
-#else
- using DatagramSocketClient client = new DatagramSocketClient(AddressFamily.InterNetwork, ProtocolType.Udp);
-#endif
-
- try
- {
- client.Bind(new IPEndPoint(IPAddress.Any, 0));
- }
- catch (SocketException)
- {
- lock (typeof(Console))
- {
- Console.WriteLine($"[Client {id}] Could not bind client socket within timeout!");
- return;
- }
- }
-#if TCP
- client.Connect(in ServerEndPoint);
-#endif
-
- EndPoint remoteEndPoint = ServerEndPoint;
-
- byte[] requestBuffer = new byte[NetworkPacket.TotalSize];
- Memory<byte> requestBufferMemory = new Memory<byte>(requestBuffer);
-
- byte[] responseBuffer = new byte[NetworkPacket.TotalSize];
- Memory<byte> responseBufferMemory = new Memory<byte>(responseBuffer);
-
- Stopwatch rttStopwatch = new Stopwatch();
- Stopwatch bandwidthStopwatch = new Stopwatch();
-
- long minRttTicks = int.MaxValue, maxRttTicks = int.MinValue;
- long minRttMs = int.MaxValue, maxRttMs = int.MinValue;
-
- for (int i = 0; i < packetsToSend; i++)
- {
- Encoding.UTF8.GetBytes($"[Client {id}] Hello World! (Packet {i})").CopyTo(requestBufferMemory);
-
- rttStopwatch.Start();
- bandwidthStopwatch.Start();
-
-#if TCP
- TransmissionResult sendResult = client.Send(requestBuffer);
-#else
- TransmissionResult sendResult = client.SendTo(remoteEndPoint, requestBuffer);
-#endif
-
- bandwidthStopwatch.Stop();
- rttStopwatch.Stop();
-
-#if DEBUG
- lock (typeof(Console))
- {
- Console.WriteLine($"[Client {id}, Packet {i}] Sent {sendResult.Count} bytes to {ServerEndPoint}");
- Console.WriteLine($"[Client {id}, Packet {i}] >>>> {Encoding.UTF8.GetString(requestBufferMemory.Span)}");
- }
-#endif
-
- rttStopwatch.Start();
- bandwidthStopwatch.Start();
-
-#if TCP
- TransmissionResult receiveResult = client.Receive(responseBuffer);
-#else
- TransmissionResult receiveResult = client.ReceiveFrom(ref remoteEndPoint, responseBuffer);
-#endif
-
- bandwidthStopwatch.Stop();
- rttStopwatch.Stop();
-
-#if DEBUG
- lock (typeof(Console))
- {
- Console.WriteLine($"[Client {id}, Packet {i}] Received {receiveResult.Count} bytes from {remoteEndPoint}");
- Console.WriteLine($"[Client {id}, Packet {i}] <<<< {Encoding.UTF8.GetString(responseBufferMemory.Span)}");
- }
-#endif
-
- lock (typeof(Console))
- {
- if (!activeTasks.Contains((int)id))
- {
- activeTasks.Add((int)id);
- }
-
-#if DEBUG
- Console.WriteLine($"[Client {id}] Client Round Trip Time: {rttStopwatch.ElapsedTicks} ticks ({rttStopwatch.ElapsedMilliseconds} ms)");
-#endif
- minRttTicks = rttStopwatch.ElapsedTicks < minRttTicks
- ? rttStopwatch.ElapsedTicks
- : minRttTicks;
-
- minRttMs = rttStopwatch.ElapsedMilliseconds < minRttMs
- ? rttStopwatch.ElapsedMilliseconds
- : minRttMs;
-
- maxRttTicks = rttStopwatch.ElapsedTicks > maxRttTicks
- ? rttStopwatch.ElapsedTicks
- : maxRttTicks;
-
- maxRttMs = rttStopwatch.ElapsedMilliseconds > maxRttMs
- ? rttStopwatch.ElapsedMilliseconds
- : maxRttMs;
-
- rttStopwatch.Reset();
- }
- }
-
-#if TCP
- client.Disconnect(true);
- client.Shutdown(SocketShutdown.Both);
-#endif
-
- long millis = bandwidthStopwatch.ElapsedMilliseconds;
- double megabytes = packetsToSend * NetworkPacket.DataSize / 1_000_000.0;
- double bandwidth = megabytes / (millis / 1000.0);
-
- clientBandwidths[(int)id] = bandwidth;
-
- lock (typeof(Console))
- {
- Console.WriteLine($"[Client {id}] Sent {packetsToSend} packets to {ServerEndPoint} in {millis} milliseconds");
- Console.WriteLine($"[Client {id}] Approximate bandwidth: {bandwidth:F3} MBps");
-
- Console.WriteLine($"[Client {id}] Min RTT: {minRttTicks} ticks, {minRttMs} ms");
- Console.WriteLine($"[Client {id}] Max RTT: {maxRttTicks} ticks, {maxRttMs} ms");
-
- Console.WriteLine($"[Client {id}] Stopping client...");
- }
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- throw;
- }
- }
-
- for (int clientId = 0; clientId < clientCount; clientId++)
- {
- clientTasks[clientId] = Task.Factory.StartNew(ClientTask, clientId, TaskCreationOptions.LongRunning);
- }
-
- await Task.WhenAll(clientTasks);
-
- int totalActiveThreads = 0;
- for (int i = 0; i < clientCount; i++)
- {
- Task clientThread = clientTasks[i];
-
- bool threadWasActive = activeTasks.Contains(i);
- if (threadWasActive)
- {
- totalActiveThreads++;
- }
-
- Console.WriteLine($"[Client task {i}] Approx bandwidth: {clientBandwidths[i]}, was active? {threadWasActive}");
- }
-
- Console.WriteLine($"Total server bandwidth: {clientBandwidths.Sum():F3} MBps, Total Active Threads: {totalActiveThreads}, Total Inactive Threads: {clientCount - totalActiveThreads}");
- }
-
- private static async Task TestSocketServer()
- {
- try
- {
-#if TCP
- StreamSocketServerOptions serverOptions = new StreamSocketServerOptions(NetworkPacket.TotalSize,
- Environment.ProcessorCount, (ushort) Environment.ProcessorCount);
-
- using StreamSocketServer server = new StreamSocketServer(AddressFamily.InterNetwork,
- ProtocolType.Tcp, SocketServer.DefaultPacketHandler, serverOptions);
-#else
- DatagramSocketServerOptions serverOptions = new DatagramSocketServerOptions(NetworkPacket.TotalSize,
- Environment.ProcessorCount, (ushort) Environment.ProcessorCount);
-
- using DatagramSocketServer server = new DatagramSocketServer(AddressFamily.InterNetwork,
- ProtocolType.Udp, SocketServer.DefaultPacketHandler, serverOptions);
-#endif
-
- server.Bind(in ServerEndPoint);
-
- await server.RunAsync();
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex);
- throw;
- }
- }
-
- #endregion Socket Tests
}
}
\ No newline at end of file