NetSharp

NetSharp.git
git clone git://git.lenczewski.org/NetSharp.git
Log | Files | Refs | README | LICENSE

commit 83d8a0f31870be6e1f7d4d612ab6803d79bf9120
parent f30b7d469c349902f22371419655e350df558bd5
Author: Mikolaj Lenczewski <mikolaj.lenczewski308@gmail.com>
Date:   Thu, 23 Apr 2020 21:30:39 +0100

Added socket client benchmarks. Fixed invalid StreamSocketClient SendAsync method. Added warnings when sending more than 10_000 packets during benchmarks.

Diffstat:
MNetSharp/NetSharp/NetSharp.xml | 845+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
MNetSharp/NetSharp/Sockets/Stream/StreamSocketClient.cs | 22+++++++++++-----------
ANetSharp/NetSharpExamples/Benchmarks/TcpSocketClientAsyncBenchmark.cs | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharpExamples/Benchmarks/TcpSocketClientSyncBenchmark.cs | 124+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MNetSharp/NetSharpExamples/Benchmarks/TcpSocketServerBenchmark.cs | 12+++++++++++-
ANetSharp/NetSharpExamples/Benchmarks/UdpSocketClientAsyncBenchmark.cs | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharpExamples/Benchmarks/UdpSocketClientSyncBenchmark.cs | 102+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MNetSharp/NetSharpExamples/Benchmarks/UdpSocketServerBenchmark.cs | 12+++++++++++-
MNetSharp/NetSharpExamples/Examples/TcpSocketClientExample.cs | 3+++
MNetSharp/NetSharpExamples/Examples/TcpSocketServerExample.cs | 3+++
MNetSharp/NetSharpExamples/Examples/UdpSocketClientExample.cs | 3+++
MNetSharp/NetSharpExamples/Examples/UdpSocketServerExample.cs | 3+++
MNetSharp/NetSharpExamples/INetSharpExample.cs | 5+++++
MNetSharp/NetSharpExamples/NetSharpExamples.xml | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
MNetSharp/NetSharpExamples/Program.cs | 59++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
15 files changed, 1268 insertions(+), 257 deletions(-)

diff --git a/NetSharp/NetSharp/NetSharp.xml b/NetSharp/NetSharp/NetSharp.xml @@ -4,46 +4,186 @@ <name>NetSharp</name> </assembly> <members> + <member name="T:NetSharp.Packets.NetworkPacket"> + <summary> + Represents a raw packet sent across the network. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.DataSize"> + <summary> + The size in bytes of the packet data segment. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.FooterSize"> + <summary> + The size in bytes of the packet footer segment. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.HeaderSize"> + <summary> + The size in bytes of the packet header segment. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.TotalSize"> + <summary> + The total size of the packet in bytes. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.NullPacket"> + <summary> + Represents an empty packet. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.Data"> + <summary> + The data held by this packet instance. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.Footer"> + <summary> + The footer for this packet instance, holding additional metadata. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacket.Header"> + <summary> + The header for this packet instance, holding additional metadata. + </summary> + </member> <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. </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. - </exception> + <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> </member> - <member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.CreateTransmissionArgs"> - <inheritdoc /> + <member name="M:NetSharp.Packets.NetworkPacket.Deserialise(System.ReadOnlyMemory{System.Byte},NetSharp.Packets.NetworkPacket@)"> + <summary> + Deserialises the serialised packet in the given memory buffer into a new <see cref="T:NetSharp.Packets.NetworkPacket" /> instance. + </summary> + <param name="buffer"> + The memory buffer to read the serialised packet instance from. + </param> + <param name="instance"> + The deserialised instance. + </param> + <returns> + Whether the deserialisation attempt was successful. The <paramref name="instance" /> will be equal to <see cref="F:NetSharp.Packets.NetworkPacket.NullPacket" /> if the + attempt fails. + </returns> </member> - <member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> - <inheritdoc /> + <member name="M:NetSharp.Packets.NetworkPacket.Serialise(NetSharp.Packets.NetworkPacket,System.Memory{System.Byte})"> + <summary> + Serialises the given <see cref="T:NetSharp.Packets.NetworkPacket" /> instance into the given memory buffer. + </summary> + <param name="instance"> + The packet instance which should be serialised. + </param> + <param name="buffer"> + The memory buffer to write the serialised packet instance to. <see cref="F:NetSharp.Packets.NetworkPacket.TotalSize" /> bytes will be written into this buffer on success. + </param> + <returns> + Whether the serialisation attempt was successful. No bytes are written to the <paramref name="buffer" /> if the attempt fails. + </returns> + </member> + <member name="T:NetSharp.Packets.NetworkPacketFooter"> + <summary> + Represents the footer of a <see cref="T:NetSharp.Packets.NetworkPacket" />, holding additional metadata. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacketFooter.TotalSize"> + <summary> + The total size of the packet footer, in bytes. + </summary> + </member> + <member name="M:NetSharp.Packets.NetworkPacketFooter.Deserialise(System.ReadOnlyMemory{System.Byte})"> + <summary> + Deserialises the serialised packet footer in the given memory buffer into a new <see cref="T:NetSharp.Packets.NetworkPacketFooter" /> instance. + </summary> + <param name="buffer"> + The memory buffer to read the serialised packet footer instance from. + </param> + <returns> + The deserialised instance. + </returns> + </member> + <member name="M:NetSharp.Packets.NetworkPacketFooter.Serialise(NetSharp.Packets.NetworkPacketFooter,System.Memory{System.Byte})"> + <summary> + Serialises the given <see cref="T:NetSharp.Packets.NetworkPacketFooter" /> instance into the given memory buffer. + </summary> + <param name="instance"> + The packet footer instance which should be serialised. + </param> + <param name="buffer"> + The memory buffer to write the serialised packet footer instance to. + </param> + </member> + <member name="T:NetSharp.Packets.NetworkPacketHeader"> + <summary> + Represents the header of a <see cref="T:NetSharp.Packets.NetworkPacket" />, holding additional metadata. + </summary> + </member> + <member name="F:NetSharp.Packets.NetworkPacketHeader.TotalSize"> + <summary> + The total size of the packet header, in bytes. + </summary> + </member> + <member name="M:NetSharp.Packets.NetworkPacketHeader.Deserialise(System.ReadOnlyMemory{System.Byte})"> + <summary> + Deserialises the serialised packet header in the given memory buffer into a new <see cref="T:NetSharp.Packets.NetworkPacketHeader" /> instance. + </summary> + <param name="buffer"> + The memory buffer to read the serialised packet header instance from. + </param> + <returns> + The deserialised instance. + </returns> + </member> + <member name="M:NetSharp.Packets.NetworkPacketHeader.Serialise(NetSharp.Packets.NetworkPacketHeader,System.Memory{System.Byte})"> + <summary> + Serialises the given <see cref="T:NetSharp.Packets.NetworkPacketHeader" /> instance into the given memory buffer. + </summary> + <param name="instance"> + The packet header instance which should be serialised. + </param> + <param name="buffer"> + The memory buffer to write the serialised packet header instance to. + </param> </member> <member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> <inheritdoc /> </member> + <member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.CreateTransmissionArgs"> + <inheritdoc /> + </member> <member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.DestroyTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> <inheritdoc /> </member> <member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"> <inheritdoc /> </member> + <member name="M:NetSharp.Sockets.Datagram.DatagramSocketClient.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <inheritdoc /> + </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. </summary> - <param name="serverOptions">Additional options to configure the server.</param> - <inheritdoc /> - </member> - <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.CreateTransmissionArgs"> + <param name="serverOptions"> + Additional options to configure the server. + </param> <inheritdoc /> </member> - <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> <inheritdoc /> </member> - <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> + <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.CreateTransmissionArgs"> <inheritdoc /> </member> <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.DestroyTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> @@ -52,6 +192,9 @@ <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"> <inheritdoc /> </member> + <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <inheritdoc /> + </member> <member name="M:NetSharp.Sockets.Datagram.DatagramSocketServer.RunAsync(System.Threading.CancellationToken)"> <inheritdoc /> </member> @@ -60,158 +203,191 @@ Abstract base class for clients. </summary> </member> - <member name="T:NetSharp.Sockets.SocketClient.AsyncTransmissionToken"> + <member name="M:NetSharp.Sockets.SocketClient.#ctor(System.Net.Sockets.AddressFamily@,System.Net.Sockets.SocketType@,System.Net.Sockets.ProtocolType@,System.Int32@,System.UInt16@)"> <summary> - A state token for asynchronous network IO operations. + 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> + <param name="connectionProtocolType"> + The protocol type that the underlying connection should use. + </param> + <param name="pooledBufferMaxSize"> + The maximum size in bytes of buffers held in the buffer pool. + </param> + <param name="preallocatedTransmissionArgs"> + The number of transmission args to preallocate. + </param> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.CompletionSource"> + <member name="M:NetSharp.Sockets.SocketClient.Connect(System.Net.EndPoint@)"> <summary> - The completion source which wraps the event-based APM, and provides an awaitable <see cref="T:System.Threading.Tasks.Task" />. + 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" />). </summary> + <param name="remoteEndPoint"> + The remote end point which to which to connect the client. + </param> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.CancellationToken"> + <member name="M:NetSharp.Sockets.SocketClient.ConnectAsync(System.Net.EndPoint@,System.Threading.CancellationToken)"> <summary> - The <see cref="T:System.Threading.CancellationToken" /> associated with the network IO operation. + 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" />). </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. + </param> + <returns> + A <see cref="T:System.Threading.Tasks.ValueTask" /> representing the connection attempt. + </returns> </member> - <member name="M:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.#ctor(System.Threading.Tasks.TaskCompletionSource{NetSharp.Utils.TransmissionResult}@,System.Threading.CancellationToken@)"> + <member name="T:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken"> <summary> - Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncTransmissionToken" /> struct. + A state token for cancelling asynchronous socket operations. </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> </member> - <member name="T:NetSharp.Sockets.SocketClient.AsyncOperationToken"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.CompletionSource"> <summary> - A state token for asynchronous socket operations. + The completion source associated with the network IO operation. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationToken.CompletionSource"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.Socket"> <summary> - The completion source which wraps the event-based APM, and provides an awaitable <see cref="T:System.Threading.Tasks.Task" />. + The socket on which the operation was started. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationToken.CancellationToken"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgs"> <summary> - The <see cref="T:System.Threading.CancellationToken" /> associated with the socket operation. + The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance associated with the socket operation. </summary> </member> - <member name="M:NetSharp.Sockets.SocketClient.AsyncOperationToken.#ctor(System.Threading.Tasks.TaskCompletionSource{System.Boolean}@,System.Threading.CancellationToken@)"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgsPool"> <summary> - Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncOperationToken" /> struct. + The pool to which the <see cref="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgs" /> should be returned upon operation cancellation. </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> </member> - <member name="T:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken"> + <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> - A state token for cancelling asynchronous network IO operations. + 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="completionSource"> + The completion source associated with the operation. + </param> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.Socket"> + <member name="T:NetSharp.Sockets.SocketClient.AsyncOperationToken"> <summary> - The socket on which the operation was started. + A state token for asynchronous socket operations. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.TransmissionArgs"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationToken.CancellationToken"> <summary> - The <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance associated with the network IO operation. + The <see cref="T:System.Threading.CancellationToken" /> associated with the socket operation. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.TransmissionArgsPool"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationToken.CompletionSource"> <summary> - The pool to which the <see cref="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.TransmissionArgs" /> should be returned upon operation cancellation. + 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.AsyncTransmissionCancellationToken.CompletionSource"> + <member name="M:NetSharp.Sockets.SocketClient.AsyncOperationToken.#ctor(System.Threading.Tasks.TaskCompletionSource{System.Boolean}@,System.Threading.CancellationToken@)"> <summary> - The completion source associated with the network IO operation. + 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> </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}@)"> + <member name="T:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken"> <summary> - Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken" /> struct. + A state token for cancelling asynchronous network IO operations. </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="completionSource">The completion source associated with the operation.</param> </member> - <member name="T:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.CompletionSource"> <summary> - A state token for cancelling asynchronous socket operations. + The completion source associated with the network IO operation. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.Socket"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.Socket"> <summary> The socket on which the operation was started. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgs"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.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 network IO operation. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.TransmissionArgsPool"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionCancellationToken.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.AsyncTransmissionCancellationToken.TransmissionArgs" /> should be returned upon operation cancellation. </summary> </member> - <member name="F:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken.CompletionSource"> + <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> - The completion source associated with the network IO operation. + 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="completionSource"> + The completion source associated with the operation. + </param> </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}@)"> + <member name="T:NetSharp.Sockets.SocketClient.AsyncTransmissionToken"> <summary> - Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncOperationCancellationToken" /> struct. + A state token for asynchronous network IO operations. </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="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@)"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.CancellationToken"> <summary> - Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient" /> class. + The <see cref="T:System.Threading.CancellationToken" /> associated with the network IO operation. </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> - <param name="connectionProtocolType">The protocol type that the underlying connection should use.</param> - <param name="maxPooledBufferLength">The maximum length of a pooled network IO buffer.</param> - <param name="preallocatedTransmissionArgs">The number of transmission args to preallocate.</param> </member> - <member name="M:NetSharp.Sockets.SocketClient.Connect(System.Net.EndPoint@)"> + <member name="F:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.CompletionSource"> <summary> - 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" />). + The completion source which wraps the event-based APM, and provides an awaitable <see cref="T:System.Threading.Tasks.Task" />. </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)"> + <member name="M:NetSharp.Sockets.SocketClient.AsyncTransmissionToken.#ctor(System.Threading.Tasks.TaskCompletionSource{NetSharp.Utils.TransmissionResult}@,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" />). + Constructs a new instance of the <see cref="T:NetSharp.Sockets.SocketClient.AsyncTransmissionToken" /> struct. </summary> - <param name="remoteEndPoint">The remote end point which to which to connect the client.</param> + <param name="completionSource"> + The completion source to trigger when the IO operation completes. + </param> <param name="cancellationToken"> - The <see cref="T:System.Threading.CancellationToken" /> upon whose cancellation the connection attempt should be aborted. + The cancellation token to observe during the operation. </param> - <returns>A <see cref="T:System.Threading.Tasks.ValueTask" /> representing the connection attempt.</returns> </member> <member name="T:NetSharp.Sockets.SocketConnection"> <summary> Abstract base class for clients and servers. </summary> - TODO add access to socket options - </member> - <member name="F:NetSharp.Sockets.SocketConnection.Connection"> - <summary> - The underlying <see cref="T:System.Net.Sockets.Socket" /> which provides access to network operations. - </summary> + TODO implement better protections for accessing socket options </member> <member name="F:NetSharp.Sockets.SocketConnection.BufferPool"> <summary> @@ -220,89 +396,152 @@ </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="F:NetSharp.Sockets.SocketConnection.Connection"> + <summary> + The underlying <see cref="T:System.Net.Sockets.Socket" /> which provides access to network operations. </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. </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="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="pooledBufferMaxSize"> + The maximum size in bytes of buffers held in the buffer pool. + </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"> + <member name="P:NetSharp.Sockets.SocketConnection.LocalEndPoint"> <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. + The local endpoint to which the underlying <see cref="T:System.Net.Sockets.Socket" /> is bound. </summary> - <returns>The configured <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance.</returns> </member> - <member name="M:NetSharp.Sockets.SocketConnection.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <member name="M:NetSharp.Sockets.SocketConnection.CanTransmissionArgsBeReused(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 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 that should be reset.</param> + <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.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> + <member name="M:NetSharp.Sockets.SocketConnection.CreateTransmissionArgs"> <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 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> - <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> + <returns> + The configured <see cref="T:System.Net.Sockets.SocketAsyncEventArgs" /> instance. + </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. + <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)"> + <member name="M:NetSharp.Sockets.SocketConnection.Dispose(System.Boolean)"> <summary> - Delegate method to handle asynchronous network IO completion via the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event. + Disposes of managed and unmanaged resources used by the <see cref="T:NetSharp.Sockets.SocketConnection" /> class. </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="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.Bind(System.Net.EndPoint@)"> + <member name="M:NetSharp.Sockets.SocketConnection.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"> <summary> - Binds the underlying socket. + Delegate method to handle asynchronous network IO completion via the <see cref="E:System.Net.Sockets.SocketAsyncEventArgs.Completed" /> event. </summary> - <param name="localEndPoint">The end point to which the socket should be bound.</param> + <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> </member> - <member name="M:NetSharp.Sockets.SocketConnection.Shutdown(System.Net.Sockets.SocketShutdown)"> + <member name="M:NetSharp.Sockets.SocketConnection.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> <summary> - Shuts down the underlying socket. + 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="how">Which socket transmission functions should be shut down on the socket.</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.Dispose(System.Boolean)"> + <member name="M:NetSharp.Sockets.SocketConnection.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Boolean)"> + <inheritdoc cref="M:System.Net.Sockets.Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Boolean)" /> + </member> + <member name="M:NetSharp.Sockets.SocketConnection.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Byte[])"> + <inheritdoc cref="M:System.Net.Sockets.Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Byte[])" /> + </member> + <member name="M:NetSharp.Sockets.SocketConnection.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Int32)"> + <inheritdoc cref="M:System.Net.Sockets.Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Int32)" /> + </member> + <member name="M:NetSharp.Sockets.SocketConnection.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Object)"> + <inheritdoc cref="M:System.Net.Sockets.Socket.SetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Object)" /> + </member> + <member name="M:NetSharp.Sockets.SocketConnection.Bind(System.Net.EndPoint@)"> <summary> - Disposes of managed and unmanaged resources used by the <see cref="T:NetSharp.Sockets.SocketConnection" /> class. + Binds the underlying socket. </summary> - <param name="disposing">Whether this call was made by a call to <see cref="M:NetSharp.Sockets.SocketConnection.Dispose" />.</param> + <param name="localEndPoint"> + The end point to which the socket should be bound. + </param> </member> <member name="M:NetSharp.Sockets.SocketConnection.Dispose"> <inheritdoc /> </member> + <member name="M:NetSharp.Sockets.SocketConnection.GetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName)"> + <inheritdoc cref="M:System.Net.Sockets.Socket.GetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName)" /> + </member> + <member name="M:NetSharp.Sockets.SocketConnection.GetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Int32)"> + <inheritdoc cref="M:System.Net.Sockets.Socket.GetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Int32)" /> + </member> + <member name="M:NetSharp.Sockets.SocketConnection.GetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Byte[])"> + <inheritdoc cref="M:System.Net.Sockets.Socket.GetSocketOption(System.Net.Sockets.SocketOptionLevel,System.Net.Sockets.SocketOptionName,System.Byte[])" /> + </member> + <member name="M:NetSharp.Sockets.SocketConnection.Shutdown(System.Net.Sockets.SocketShutdown)"> + <summary> + Shuts down the underlying socket. + </summary> + <param name="how"> + Which socket transmission functions should be shut down on the socket. + </param> + </member> <member name="T:NetSharp.Sockets.SocketServerPacketHandler"> <summary> Represents a method for serving request packets. This method should not throw any errors. </summary> - <param name="requestPacket">The request packet received by the server.</param> - <param name="clientEndPoint">The client from which the packet was received.</param> + <param name="requestPacket"> + The request packet received by the server. + </param> + <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" />. + 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" />. </returns> </member> <member name="T:NetSharp.Sockets.SocketServer"> @@ -319,35 +558,54 @@ <summary> 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> - <param name="connectionProtocolType">The protocol type that the underlying connection should use.</param> - <param name="packetHandler">The packet handler delegate to use to respond to incoming requests.</param> - <param name="maxPooledBufferLength">The maximum length of a pooled network IO buffer.</param> - <param name="preallocatedTransmissionArgs">The number of transmission args to preallocate.</param> + <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> + <param name="connectionProtocolType"> + The protocol type that the underlying connection should use. + </param> + <param name="packetHandler"> + The packet handler delegate to use to respond to incoming requests. + </param> + <param name="pooledBufferMaxSize"> + The maximum size in bytes of buffers held in the buffer pool. + </param> + <param name="preallocatedTransmissionArgs"> + The number of transmission args to preallocate. + </param> </member> <member name="M:NetSharp.Sockets.SocketServer.DefaultPacketHandler(NetSharp.Packets.NetworkPacket@,System.Net.EndPoint@)"> <summary> The default request packet handler for servers. Simply echoes back any received packets. </summary> - <param name="request">The request packet that was received.</param> - <param name="remoteEndPoint">The client from which the packet was received.</param> - <returns>The received packet.</returns> + <param name="request"> + The request packet that was received. + </param> + <param name="remoteEndPoint"> + The client from which the packet was received. + </param> + <returns> + The received packet. + </returns> </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. </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> - </member> - <member name="M:NetSharp.Sockets.Stream.StreamSocketClient.CreateTransmissionArgs"> - <inheritdoc /> + <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.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <member name="M:NetSharp.Sockets.Stream.StreamSocketClient.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> <inheritdoc /> </member> - <member name="M:NetSharp.Sockets.Stream.StreamSocketClient.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> + <member name="M:NetSharp.Sockets.Stream.StreamSocketClient.CreateTransmissionArgs"> <inheritdoc /> </member> <member name="M:NetSharp.Sockets.Stream.StreamSocketClient.DestroyTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> @@ -356,20 +614,22 @@ <member name="M:NetSharp.Sockets.Stream.StreamSocketClient.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"> <inheritdoc /> </member> + <member name="M:NetSharp.Sockets.Stream.StreamSocketClient.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <inheritdoc /> + </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. </summary> - <param name="serverOptions">Additional options to configure the server.</param> - <inheritdoc /> - </member> - <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.CreateTransmissionArgs"> + <param name="serverOptions"> + Additional options to configure the server. + </param> <inheritdoc /> </member> - <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> <inheritdoc /> </member> - <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.CanTransmissionArgsBeReused(System.Net.Sockets.SocketAsyncEventArgs@)"> + <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.CreateTransmissionArgs"> <inheritdoc /> </member> <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.DestroyTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> @@ -378,6 +638,9 @@ <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.HandleIoCompleted(System.Object,System.Net.Sockets.SocketAsyncEventArgs)"> <inheritdoc /> </member> + <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.ResetTransmissionArgs(System.Net.Sockets.SocketAsyncEventArgs)"> + <inheritdoc /> + </member> <member name="M:NetSharp.Sockets.Stream.StreamSocketServer.RunAsync(System.Threading.CancellationToken)"> <inheritdoc /> </member> @@ -385,8 +648,12 @@ <summary> Represents a concurrent two-way dictionary, that can be indexed by either a key or a value. </summary> - <typeparam name="K">The type of key that will be stored.</typeparam> - <typeparam name="V">The type of value that will be stored.</typeparam> + <typeparam name="K"> + The type of key that will be stored. + </typeparam> + <typeparam name="V"> + The type of value that will be stored. + </typeparam> </member> <member name="F:NetSharp.Utils.BiDictionary`2.keyToValueMap"> <summary> @@ -407,15 +674,23 @@ <summary> Indexes this instance with the given value. </summary> - <param name="index">The value whose key to get or set.</param> - <returns>The fetched key.</returns> + <param name="index"> + The value whose key to get or set. + </param> + <returns> + The fetched key. + </returns> </member> <member name="P:NetSharp.Utils.BiDictionary`2.Item(`0)"> <summary> Indexes this instance with the given key. </summary> - <param name="index">The key whose value to get or set.</param> - <returns>The fetched value.</returns> + <param name="index"> + The key whose value to get or set. + </param> + <returns> + The fetched value. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.Clear"> <summary> @@ -426,79 +701,135 @@ <summary> Whether this instance contains the given key. </summary> - <param name="key">The key to check.</param> - <returns>Whether the given key was found.</returns> + <param name="key"> + The key to check. + </param> + <returns> + Whether the given key was found. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.ContainsValue(`1@)"> <summary> Whether this instance contains the given value. </summary> - <param name="value">The value to check.</param> - <returns>Whether the given value was found.</returns> + <param name="value"> + The value to check. + </param> + <returns> + Whether the given value was found. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.SetOrUpdateKey(`1,`0)"> <summary> Attempts to set the key associated with the given value. </summary> - <param name="value">The value whose key to set.</param> - <param name="key">The new value for the value's associated key.</param> - <returns>Whether the new key was correctly set.</returns> + <param name="value"> + The value whose key to set. + </param> + <param name="key"> + The new value for the value's associated key. + </param> + <returns> + Whether the new key was correctly set. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.SetOrUpdateValue(`0,`1)"> <summary> Attempts to set the value associated with the given key. </summary> - <param name="key">The key whose value to set.</param> - <param name="value">The new value for the key's associated value.</param> - <returns>Whether the new value was correctly set.</returns> + <param name="key"> + The key whose value to set. + </param> + <param name="value"> + The new value for the key's associated value. + </param> + <returns> + Whether the new value was correctly set. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.TryClearKey(`1@,`0@)"> <summary> Attempts to remove the key associated with the given value. </summary> - <param name="value">The value whose key to remove.</param> - <param name="key">The old key value.</param> - <returns>Whether the given value had a valid key associated with it.</returns> + <param name="value"> + The value whose key to remove. + </param> + <param name="key"> + The old key value. + </param> + <returns> + Whether the given value had a valid key associated with it. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.TryClearValue(`0@,`1@)"> <summary> Attempts to remove the value associated with the given key. </summary> - <param name="key">The key whose value to remove.</param> - <param name="value">The old value.</param> - <returns>Whether the given key had a valid valid associated with it.</returns> + <param name="key"> + The key whose value to remove. + </param> + <param name="value"> + The old value. + </param> + <returns> + Whether the given key had a valid valid associated with it. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.TryGetKey(`1@,`0@)"> <summary> Attempts to get the key associated with the given value. </summary> - <param name="value">The value whose key to get.</param> - <param name="key">The returned key.</param> - <returns>Whether the given value has a valid key associated with it.</returns> + <param name="value"> + The value whose key to get. + </param> + <param name="key"> + The returned key. + </param> + <returns> + Whether the given value has a valid key associated with it. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.TryGetValue(`0@,`1@)"> <summary> Attempts to get the value associated with the given key. </summary> - <param name="key">The key whose value to get.</param> - <param name="value">The returned value.</param> - <returns>Whether the given key as a valid value associated with it.</returns> + <param name="key"> + The key whose value to get. + </param> + <param name="value"> + The returned value. + </param> + <returns> + Whether the given key as a valid value associated with it. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.TrySetKey(`1@,`0@)"> <summary> Attempts to set the key associated with the given value. </summary> - <param name="value">The value whose key to set.</param> - <param name="key">The key which should be set for the given value.</param> - <returns>Whether the given value was successfully set.</returns> + <param name="value"> + The value whose key to set. + </param> + <param name="key"> + The key which should be set for the given value. + </param> + <returns> + Whether the given value was successfully set. + </returns> </member> <member name="M:NetSharp.Utils.BiDictionary`2.TrySetValue(`0@,`1@)"> <summary> Attempts to set the value associated with the given key. </summary> - <param name="key">The key whose value to set.</param> - <param name="value">The value which should be set for the given key.</param> - <returns>Whether the given key was successfully set.</returns> + <param name="key"> + The key whose value to set. + </param> + <param name="value"> + The value which should be set for the given key. + </param> + <returns> + Whether the given key was successfully set. + </returns> </member> <member name="T:NetSharp.Utils.Conversion.EndianAwareBitConverter"> <summary> @@ -574,85 +905,104 @@ <summary> Provides a lightweight implementation of an object pool for classes. </summary> - <typeparam name="T">The type of item stored in the pool.</typeparam> + <typeparam name="T"> + The type of item stored in the pool. + </typeparam> </member> - <member name="T:NetSharp.Utils.SlimObjectPool`1.CreateObjectDelegate"> + <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> - Delegate method for creating fresh <typeparamref name="T" /> instances to be stored in the pool. + Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1" /> class. </summary> - <returns>A configured <typeparamref name="T" /> instance.</returns> + <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> + <param name="destroyDelegate"> + The delegate method to use to destroy pooled object instances that cannot be reused. + </param> + <param name="rebufferPredicate"> + The delegate method to use to decide whether an instance can be reused. + </param> + <param name="baseCollection"> + The underlying pooled object buffer to use. + </param> </member> - <member name="T:NetSharp.Utils.SlimObjectPool`1.CanRebufferObjectPredicate"> + <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> - 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. + Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1" /> class. </summary> - <param name="instance">The instance to check.</param> - <returns>Whether the given instance should be placed back into the pool.</returns> + <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> + <param name="destroyDelegate"> + The delegate method to use to destroy pooled object instances that cannot be reused. + </param> + <param name="rebufferPredicate"> + The delegate method to use to decide whether an instance can be reused. + </param> </member> - <member name="T:NetSharp.Utils.SlimObjectPool`1.ResetObjectDelegate"> + <member name="T:NetSharp.Utils.SlimObjectPool`1.CanRebufferObjectPredicate"> <summary> - Delegate method to reset a used <paramref name="instance" /> before placing it back into the pool. + 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 which should be reset.</param> + <param name="instance"> + The instance to check. + </param> + <returns> + Whether the given instance should be placed back into the pool. + </returns> </member> - <member name="T:NetSharp.Utils.SlimObjectPool`1.DestroyObjectDelegate"> + <member name="T:NetSharp.Utils.SlimObjectPool`1.CreateObjectDelegate"> <summary> - Delegate method to destroy a used <paramref name="instance" /> which cannot be reused. + Delegate method for creating fresh <typeparamref name="T" /> instances to be stored in the pool. </summary> - <param name="instance">The instance to destroy.</param> + <returns> + A configured <typeparamref name="T" /> instance. + </returns> </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}@)"> + <member name="T:NetSharp.Utils.SlimObjectPool`1.DestroyObjectDelegate"> <summary> - Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1" /> class. + Delegate method to destroy a used <paramref name="instance" /> which cannot be reused. </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> - <param name="destroyDelegate">The delegate method to use to destroy pooled object instances that cannot be reused.</param> - <param name="rebufferPredicate">The delegate method to use to decide whether an instance can be reused.</param> - <param name="baseCollection">The underlying pooled object buffer to use.</param> + <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@)"> + <member name="T:NetSharp.Utils.SlimObjectPool`1.ResetObjectDelegate"> <summary> - Constructs a new instance of the <see cref="T:NetSharp.Utils.SlimObjectPool`1" /> class. + Delegate method to reset a used <paramref name="instance" /> before placing it back into the pool. </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> - <param name="destroyDelegate">The delegate method to use to destroy pooled object instances that cannot be reused.</param> - <param name="rebufferPredicate">The delegate method to use to decide whether an instance can be reused.</param> + <param name="instance"> + The instance which should be reset. + </param> </member> <member name="M:NetSharp.Utils.SlimObjectPool`1.Rent"> <summary> 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. </summary> - <param name="instance">The previously leased instance which should be returned.</param> + <param name="instance"> + The previously leased instance which should be returned. + </param> </member> <member name="T:NetSharp.Utils.TransmissionResult"> <summary> Represents the result of a socket transmission. </summary> </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. - </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. - </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> - <param name="remoteEndPoint">The remote end point associated with the transmission.</param> - </member> <member name="F:NetSharp.Utils.TransmissionResult.Buffer"> <summary> The byte buffer that was transmitted across the network. @@ -668,5 +1018,27 @@ The remote endpoint to which the buffer was transmitted. </summary> </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. + </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. + </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> + <param name="remoteEndPoint"> + The remote end point associated with the transmission. + </param> + </member> </members> -</doc> -\ No newline at end of file +</doc> diff --git a/NetSharp/NetSharp/Sockets/Stream/StreamSocketClient.cs b/NetSharp/NetSharp/Sockets/Stream/StreamSocketClient.cs @@ -268,15 +268,15 @@ namespace NetSharp.Sockets.Stream public TransmissionResult Receive(byte[] buffer, SocketFlags flags = SocketFlags.None) { - int bytesToReceive = buffer.Length; - int bytesReceived = 0; + int expectedBytes = buffer.Length; + int receivedBytes = 0; do { - bytesReceived += Connection.Receive(buffer, bytesReceived, bytesToReceive - bytesReceived, flags); - } while (bytesReceived != 0 && bytesReceived < bytesToReceive); + receivedBytes += Connection.Receive(buffer, receivedBytes, expectedBytes - receivedBytes, flags); + } while (receivedBytes != 0 && receivedBytes < expectedBytes); - return new TransmissionResult(in buffer, in bytesReceived, Connection.RemoteEndPoint); + return new TransmissionResult(in buffer, in receivedBytes, Connection.RemoteEndPoint); } public ValueTask<TransmissionResult> ReceiveAsync(Memory<byte> receiveBuffer, SocketFlags flags = SocketFlags.None, @@ -302,15 +302,15 @@ namespace NetSharp.Sockets.Stream public TransmissionResult Send(byte[] buffer, SocketFlags flags = SocketFlags.None) { - int bytesToSend = buffer.Length; - int bytesSent = 0; + int expectedBytes = buffer.Length; + int sentBytes = 0; do { - bytesSent += Connection.Send(buffer, bytesSent, bytesToSend - bytesSent, flags); - } while (bytesSent != 0 && bytesSent < bytesToSend); + sentBytes += Connection.Send(buffer, sentBytes, expectedBytes - sentBytes, flags); + } while (sentBytes != 0 && sentBytes < expectedBytes); - return new TransmissionResult(in buffer, in bytesSent, Connection.RemoteEndPoint); + return new TransmissionResult(in buffer, in sentBytes, Connection.RemoteEndPoint); } public ValueTask<TransmissionResult> SendAsync(Memory<byte> sendBuffer, SocketFlags flags = SocketFlags.None, @@ -325,7 +325,7 @@ namespace NetSharp.Sockets.Stream args.SocketFlags = flags; args.UserToken = new AsyncTransmissionToken(in tcs, in cancellationToken); - if (Connection.SendToAsync(args)) return new ValueTask<TransmissionResult>(tcs.Task); + if (Connection.SendAsync(args)) return new ValueTask<TransmissionResult>(tcs.Task); TransmissionResult result = new TransmissionResult(in args); diff --git a/NetSharp/NetSharpExamples/Benchmarks/TcpSocketClientAsyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/TcpSocketClientAsyncBenchmark.cs @@ -0,0 +1,123 @@ +using NetSharp.Packets; +using NetSharp.Sockets.Stream; +using NetSharp.Utils; + +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NetSharpExamples.Benchmarks +{ + public class TcpSocketClientAsyncBenchmark : INetSharpExample + { + /// <summary> + /// Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + /// </summary> + private const int PacketCount = 1_000_000; + + private static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12368); + + /// <inheritdoc /> + public string Name { get; } = "TCP Socket Client Benchmark (Asynchronous)"; + + private Task ServerTask(CancellationToken cancellationToken) + { + Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + server.Bind(ServerEndPoint); + + byte[] transmissionBuffer = new byte[NetworkPacket.TotalSize]; + + server.Listen(1); + Socket clientSocket = server.Accept(); + + while (!cancellationToken.IsCancellationRequested) + { + int expectedBytes = transmissionBuffer.Length; + + int receivedBytes = 0; + do + { + receivedBytes += clientSocket.Receive(transmissionBuffer, receivedBytes, expectedBytes - receivedBytes, SocketFlags.None); + } while (receivedBytes != 0 && receivedBytes < expectedBytes); + + if (receivedBytes == 0) + { + break; + } + + int sentBytes = 0; + do + { + sentBytes += clientSocket.Send(transmissionBuffer, sentBytes, expectedBytes - sentBytes, SocketFlags.None); + } while (sentBytes != 0 && sentBytes < expectedBytes); + + if (sentBytes == 0) + { + break; + } + } + + server.Shutdown(SocketShutdown.Both); + server.Close(); + + return Task.CompletedTask; + } + + /// <inheritdoc /> + public async Task RunAsync() + { + Console.WriteLine($"TCP Client Benchmark started!"); + + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent. This could take a long time (maybe more than a minute)!"); + } + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken)state), serverCts.Token, TaskCreationOptions.LongRunning); + + BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); + + StreamSocketClientOptions clientOptions = new StreamSocketClientOptions((ushort)2); + using StreamSocketClient client = new StreamSocketClient(AddressFamily.InterNetwork, ProtocolType.Tcp, clientOptions); + + await client.ConnectAsync(in ServerEndPoint); + + byte[] sendBuffer = new byte[NetworkPacket.TotalSize]; + byte[] receiveBuffer = new byte[NetworkPacket.TotalSize]; + + for (int i = 0; i < PacketCount; i++) + { + byte[] packetBuffer = Encoding.UTF8.GetBytes($"[Client 0] Hello World! (Packet {i})"); + packetBuffer.CopyTo(sendBuffer, 0); + + benchmarkHelper.StartBandwidthStopwatch(); + benchmarkHelper.StartRttStopwatch(); + TransmissionResult sendResult = await client.SendAsync(sendBuffer); + + TransmissionResult receiveResult = await client.ReceiveAsync(receiveBuffer); + benchmarkHelper.StopRttStopwatch(); + benchmarkHelper.StopBandwidthStopwatch(); + + benchmarkHelper.UpdateRttStats(0); + benchmarkHelper.ResetRttStopwatch(); + } + + benchmarkHelper.PrintBandwidthStats(0, PacketCount, NetworkPacket.TotalSize); + benchmarkHelper.PrintRttStats(0); + + serverCts.Cancel(); + try + { + serverTask.Dispose(); + } + catch (Exception) { } + + Console.WriteLine($"TCP Client Benchmark finished!"); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/TcpSocketClientSyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/TcpSocketClientSyncBenchmark.cs @@ -0,0 +1,123 @@ +using NetSharp.Packets; +using NetSharp.Sockets.Stream; +using NetSharp.Utils; + +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NetSharpExamples.Benchmarks +{ + public class TcpSocketClientSyncBenchmark : INetSharpExample + { + /// <summary> + /// Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + /// </summary> + private const int PacketCount = 1_000_000; + + private static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12358); + + /// <inheritdoc /> + public string Name { get; } = "TCP Socket Client Benchmark (Synchronous)"; + + private Task ServerTask(CancellationToken cancellationToken) + { + Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + server.Bind(ServerEndPoint); + + byte[] transmissionBuffer = new byte[NetworkPacket.TotalSize]; + + server.Listen(1); + Socket clientSocket = server.Accept(); + + while (!cancellationToken.IsCancellationRequested) + { + int expectedBytes = transmissionBuffer.Length; + + int receivedBytes = 0; + do + { + receivedBytes += clientSocket.Receive(transmissionBuffer, receivedBytes, expectedBytes - receivedBytes, SocketFlags.None); + } while (receivedBytes != 0 && receivedBytes < expectedBytes); + + if (receivedBytes == 0) + { + break; + } + + int sentBytes = 0; + do + { + sentBytes += clientSocket.Send(transmissionBuffer, sentBytes, expectedBytes - sentBytes, SocketFlags.None); + } while (sentBytes != 0 && sentBytes < expectedBytes); + + if (sentBytes == 0) + { + break; + } + } + + server.Shutdown(SocketShutdown.Both); + server.Close(); + + return Task.CompletedTask; + } + + /// <inheritdoc /> + public async Task RunAsync() + { + Console.WriteLine($"TCP Client Benchmark started!"); + + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent. This could take a long time (maybe more than a minute)!"); + } + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken)state), serverCts.Token, TaskCreationOptions.LongRunning); + + BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); + + StreamSocketClientOptions clientOptions = new StreamSocketClientOptions((ushort)2); + using StreamSocketClient client = new StreamSocketClient(AddressFamily.InterNetwork, ProtocolType.Tcp, clientOptions); + + client.Connect(in ServerEndPoint); + + byte[] sendBuffer = new byte[NetworkPacket.TotalSize]; + byte[] receiveBuffer = new byte[NetworkPacket.TotalSize]; + + for (int i = 0; i < PacketCount; i++) + { + byte[] packetBuffer = Encoding.UTF8.GetBytes($"[Client 0] Hello World! (Packet {i})"); + packetBuffer.CopyTo(sendBuffer, 0); + + benchmarkHelper.StartBandwidthStopwatch(); + benchmarkHelper.StartRttStopwatch(); + TransmissionResult sendResult = client.Send(sendBuffer); + + TransmissionResult receiveResult = client.Receive(receiveBuffer); + benchmarkHelper.StopRttStopwatch(); + benchmarkHelper.StopBandwidthStopwatch(); + + benchmarkHelper.UpdateRttStats(0); + benchmarkHelper.ResetRttStopwatch(); + } + + benchmarkHelper.PrintBandwidthStats(0, PacketCount, NetworkPacket.TotalSize); + benchmarkHelper.PrintRttStats(0); + + serverCts.Cancel(); + try + { + serverTask.Dispose(); + } + catch (Exception) { } + + Console.WriteLine($"TCP Client Benchmark finished!"); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/TcpSocketServerBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/TcpSocketServerBenchmark.cs @@ -14,12 +14,18 @@ namespace NetSharpExamples.Benchmarks { public class TcpSocketServerBenchmark : INetSharpExample { + /// <summary> + /// Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + /// </summary> private const int PacketCount = 1_000_000; private static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12348); private double[] ClientBandwidths; + /// <inheritdoc /> + public string Name { get; } = "TCP Socket Server Benchmark"; + private Task BenchmarkClientTask(object idObj) { int id = (int)idObj; @@ -77,7 +83,6 @@ namespace NetSharpExamples.Benchmarks benchmarkHelper.StopBandwidthStopwatch(); benchmarkHelper.UpdateRttStats(id); - benchmarkHelper.ResetRttStopwatch(); } @@ -101,6 +106,11 @@ namespace NetSharpExamples.Benchmarks Console.WriteLine($"TCP Server Benchmark started!"); + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent. This could take a long time (maybe more than a minute)!"); + } + StreamSocketServerOptions serverOptions = new StreamSocketServerOptions(clientCount, (ushort)clientCount); StreamSocketServer server = new StreamSocketServer(AddressFamily.InterNetwork, ProtocolType.Tcp, diff --git a/NetSharp/NetSharpExamples/Benchmarks/UdpSocketClientAsyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/UdpSocketClientAsyncBenchmark.cs @@ -0,0 +1,99 @@ +using NetSharp.Packets; +using NetSharp.Sockets.Datagram; +using NetSharp.Utils; + +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NetSharpExamples.Benchmarks +{ + public class UdpSocketClientAsyncBenchmark : INetSharpExample + { + /// <summary> + /// Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + /// </summary> + private const int PacketCount = 1_000_000; + + private static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12367); + + /// <inheritdoc /> + public string Name { get; } = "UDP Socket Client Benchmark (Asynchronous)"; + + private Task ServerTask(CancellationToken cancellationToken) + { + Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + server.Bind(ServerEndPoint); + + byte[] transmissionBuffer = new byte[NetworkPacket.TotalSize]; + + EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + + while (!cancellationToken.IsCancellationRequested) + { + server.ReceiveFrom(transmissionBuffer, ref remoteEndPoint); + + server.SendTo(transmissionBuffer, remoteEndPoint); + } + + server.Close(); + + return Task.CompletedTask; + } + + /// <inheritdoc /> + public async Task RunAsync() + { + Console.WriteLine($"UDP Client Benchmark started!"); + + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent. This could take a long time (maybe more than a minute)!"); + } + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken)state), serverCts.Token, TaskCreationOptions.LongRunning); + + BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); + + DatagramSocketClientOptions clientOptions = new DatagramSocketClientOptions((ushort)2); + using DatagramSocketClient client = new DatagramSocketClient(AddressFamily.InterNetwork, ProtocolType.Udp, clientOptions); + + byte[] sendBuffer = new byte[NetworkPacket.TotalSize]; + byte[] receiveBuffer = new byte[NetworkPacket.TotalSize]; + + for (int i = 0; i < PacketCount; i++) + { + byte[] packetBuffer = Encoding.UTF8.GetBytes($"[Client 0] Hello World! (Packet {i})"); + packetBuffer.CopyTo(sendBuffer, 0); + + benchmarkHelper.StartBandwidthStopwatch(); + benchmarkHelper.StartRttStopwatch(); + TransmissionResult sendResult = await client.SendToAsync(ServerEndPoint, sendBuffer); + + TransmissionResult receiveResult = await client.ReceiveFromAsync(ServerEndPoint, receiveBuffer); + benchmarkHelper.StopRttStopwatch(); + benchmarkHelper.StopBandwidthStopwatch(); + + benchmarkHelper.UpdateRttStats(0); + benchmarkHelper.ResetRttStopwatch(); + } + + benchmarkHelper.PrintBandwidthStats(0, PacketCount, NetworkPacket.TotalSize); + benchmarkHelper.PrintRttStats(0); + + serverCts.Cancel(); + try + { + serverTask.Dispose(); + } + catch (Exception) { } + + Console.WriteLine($"UDP Client Benchmark finished!"); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/UdpSocketClientSyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/UdpSocketClientSyncBenchmark.cs @@ -0,0 +1,101 @@ +using NetSharp.Packets; +using NetSharp.Sockets.Datagram; +using NetSharp.Utils; + +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace NetSharpExamples.Benchmarks +{ + public class UdpSocketClientSyncBenchmark : INetSharpExample + { + /// <summary> + /// Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + /// </summary> + private const int PacketCount = 1_000_000; + + private static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12357); + + /// <inheritdoc /> + public string Name { get; } = "UDP Socket Client Benchmark (Synchronous)"; + + private Task ServerTask(CancellationToken cancellationToken) + { + Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + server.Bind(ServerEndPoint); + + byte[] transmissionBuffer = new byte[NetworkPacket.TotalSize]; + + EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + + while (!cancellationToken.IsCancellationRequested) + { + server.ReceiveFrom(transmissionBuffer, ref remoteEndPoint); + + server.SendTo(transmissionBuffer, remoteEndPoint); + } + + server.Close(); + + return Task.CompletedTask; + } + + /// <inheritdoc /> + public async Task RunAsync() + { + Console.WriteLine($"UDP Client Benchmark started!"); + + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent. This could take a long time (maybe more than a minute)!"); + } + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken)state), serverCts.Token, TaskCreationOptions.LongRunning); + + BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); + + DatagramSocketClientOptions clientOptions = new DatagramSocketClientOptions((ushort)2); + using DatagramSocketClient client = new DatagramSocketClient(AddressFamily.InterNetwork, ProtocolType.Udp, clientOptions); + + byte[] sendBuffer = new byte[NetworkPacket.TotalSize]; + byte[] receiveBuffer = new byte[NetworkPacket.TotalSize]; + + EndPoint remoteEndPoint = ServerEndPoint; + + for (int i = 0; i < PacketCount; i++) + { + byte[] packetBuffer = Encoding.UTF8.GetBytes($"[Client 0] Hello World! (Packet {i})"); + packetBuffer.CopyTo(sendBuffer, 0); + + benchmarkHelper.StartBandwidthStopwatch(); + benchmarkHelper.StartRttStopwatch(); + TransmissionResult sendResult = client.SendTo(remoteEndPoint, sendBuffer); + + TransmissionResult receiveResult = client.ReceiveFrom(ref remoteEndPoint, receiveBuffer); + benchmarkHelper.StopRttStopwatch(); + benchmarkHelper.StopBandwidthStopwatch(); + + benchmarkHelper.UpdateRttStats(0); + benchmarkHelper.ResetRttStopwatch(); + } + + benchmarkHelper.PrintBandwidthStats(0, PacketCount, NetworkPacket.TotalSize); + benchmarkHelper.PrintRttStats(0); + + serverCts.Cancel(); + try + { + serverTask.Dispose(); + } + catch (Exception) { } + + Console.WriteLine($"UDP Client Benchmark finished!"); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/UdpSocketServerBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/UdpSocketServerBenchmark.cs @@ -14,12 +14,18 @@ namespace NetSharpExamples.Benchmarks { public class UdpSocketServerBenchmark : INetSharpExample { + /// <summary> + /// Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + /// </summary> private const int PacketCount = 1_000_000; private static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12347); private double[] ClientBandwidths; + /// <inheritdoc /> + public string Name { get; } = "UDP Socket Server Benchmark"; + private Task BenchmarkClientTask(object idObj) { int id = (int)idObj; @@ -54,7 +60,6 @@ namespace NetSharpExamples.Benchmarks benchmarkHelper.StopBandwidthStopwatch(); benchmarkHelper.UpdateRttStats(id); - benchmarkHelper.ResetRttStopwatch(); } @@ -75,6 +80,11 @@ namespace NetSharpExamples.Benchmarks Console.WriteLine($"UDP Server Benchmark started!"); + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent. This could take a long time (maybe more than a minute)!"); + } + DatagramSocketServerOptions serverOptions = new DatagramSocketServerOptions(clientCount, (ushort)clientCount); DatagramSocketServer server = new DatagramSocketServer(AddressFamily.InterNetwork, ProtocolType.Udp, diff --git a/NetSharp/NetSharpExamples/Examples/TcpSocketClientExample.cs b/NetSharp/NetSharpExamples/Examples/TcpSocketClientExample.cs @@ -13,6 +13,9 @@ namespace NetSharpExamples.Examples public class TcpSocketClientExample : INetSharpExample { /// <inheritdoc /> + public string Name { get; } = "TCP Socket Client Example"; + + /// <inheritdoc /> public async Task RunAsync() { StreamSocketClientOptions clientOptions = new StreamSocketClientOptions(2); diff --git a/NetSharp/NetSharpExamples/Examples/TcpSocketServerExample.cs b/NetSharp/NetSharpExamples/Examples/TcpSocketServerExample.cs @@ -15,6 +15,9 @@ namespace NetSharpExamples.Examples public static readonly Encoding ServerEncoding = Encoding.UTF8; public static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12348); + /// <inheritdoc /> + public string Name { get; } = "TCP Socket Server Example"; + public static NetworkPacket ServerPacketHandler(in NetworkPacket request, in EndPoint remoteEndPoint) { // lock is not necessary, but means that console output is clean and not interleaved diff --git a/NetSharp/NetSharpExamples/Examples/UdpSocketClientExample.cs b/NetSharp/NetSharpExamples/Examples/UdpSocketClientExample.cs @@ -13,6 +13,9 @@ namespace NetSharpExamples.Examples public class UdpSocketClientExample : INetSharpExample { /// <inheritdoc /> + public string Name { get; } = "UDP Socket Client Example"; + + /// <inheritdoc /> public async Task RunAsync() { DatagramSocketClientOptions clientOptions = new DatagramSocketClientOptions(2); diff --git a/NetSharp/NetSharpExamples/Examples/UdpSocketServerExample.cs b/NetSharp/NetSharpExamples/Examples/UdpSocketServerExample.cs @@ -15,6 +15,9 @@ namespace NetSharpExamples.Examples public static readonly Encoding ServerEncoding = Encoding.UTF8; public static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12347); + /// <inheritdoc /> + public string Name { get; } = "UDP Socket Server Example"; + public static NetworkPacket ServerPacketHandler(in NetworkPacket request, in EndPoint remoteEndPoint) { // lock is not necessary, but means that console output is clean and not interleaved diff --git a/NetSharp/NetSharpExamples/INetSharpExample.cs b/NetSharp/NetSharpExamples/INetSharpExample.cs @@ -8,6 +8,11 @@ namespace NetSharpExamples public interface INetSharpExample { /// <summary> + /// The name of the example. + /// </summary> + string Name { get; } + + /// <summary> /// Runs the example asynchronously. /// </summary> Task RunAsync(); diff --git a/NetSharp/NetSharpExamples/NetSharpExamples.xml b/NetSharp/NetSharpExamples/NetSharpExamples.xml @@ -4,5 +4,110 @@ <name>NetSharpExamples</name> </assembly> <members> + <member name="F:NetSharpExamples.Benchmarks.TcpSocketClientAsyncBenchmark.PacketCount"> + <summary> + Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + </summary> + </member> + <member name="P:NetSharpExamples.Benchmarks.TcpSocketClientAsyncBenchmark.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Benchmarks.TcpSocketClientAsyncBenchmark.RunAsync"> + <inheritdoc /> + </member> + <member name="F:NetSharpExamples.Benchmarks.TcpSocketClientSyncBenchmark.PacketCount"> + <summary> + Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + </summary> + </member> + <member name="P:NetSharpExamples.Benchmarks.TcpSocketClientSyncBenchmark.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Benchmarks.TcpSocketClientSyncBenchmark.RunAsync"> + <inheritdoc /> + </member> + <member name="F:NetSharpExamples.Benchmarks.TcpSocketServerBenchmark.PacketCount"> + <summary> + Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + </summary> + </member> + <member name="P:NetSharpExamples.Benchmarks.TcpSocketServerBenchmark.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Benchmarks.TcpSocketServerBenchmark.RunAsync"> + <inheritdoc /> + </member> + <member name="F:NetSharpExamples.Benchmarks.UdpSocketClientAsyncBenchmark.PacketCount"> + <summary> + Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + </summary> + </member> + <member name="P:NetSharpExamples.Benchmarks.UdpSocketClientAsyncBenchmark.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Benchmarks.UdpSocketClientAsyncBenchmark.RunAsync"> + <inheritdoc /> + </member> + <member name="F:NetSharpExamples.Benchmarks.UdpSocketClientSyncBenchmark.PacketCount"> + <summary> + Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + </summary> + </member> + <member name="P:NetSharpExamples.Benchmarks.UdpSocketClientSyncBenchmark.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Benchmarks.UdpSocketClientSyncBenchmark.RunAsync"> + <inheritdoc /> + </member> + <member name="F:NetSharpExamples.Benchmarks.UdpSocketServerBenchmark.PacketCount"> + <summary> + Packets contain 8 KiB of data, so 1 000 000 packet = 8GiB. the more data the more accurate the benchmark, but the slower it will run. + </summary> + </member> + <member name="P:NetSharpExamples.Benchmarks.UdpSocketServerBenchmark.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Benchmarks.UdpSocketServerBenchmark.RunAsync"> + <inheritdoc /> + </member> + <member name="P:NetSharpExamples.Examples.TcpSocketClientExample.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Examples.TcpSocketClientExample.RunAsync"> + <inheritdoc /> + </member> + <member name="P:NetSharpExamples.Examples.TcpSocketServerExample.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Examples.TcpSocketServerExample.RunAsync"> + <inheritdoc /> + </member> + <member name="P:NetSharpExamples.Examples.UdpSocketClientExample.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Examples.UdpSocketClientExample.RunAsync"> + <inheritdoc /> + </member> + <member name="P:NetSharpExamples.Examples.UdpSocketServerExample.Name"> + <inheritdoc /> + </member> + <member name="M:NetSharpExamples.Examples.UdpSocketServerExample.RunAsync"> + <inheritdoc /> + </member> + <member name="T:NetSharpExamples.INetSharpExample"> + <summary> + Defines an example program. + </summary> + </member> + <member name="P:NetSharpExamples.INetSharpExample.Name"> + <summary> + The name of the example. + </summary> + </member> + <member name="M:NetSharpExamples.INetSharpExample.RunAsync"> + <summary> + Runs the example asynchronously. + </summary> + </member> </members> -</doc> -\ No newline at end of file +</doc> diff --git a/NetSharp/NetSharpExamples/Program.cs b/NetSharp/NetSharpExamples/Program.cs @@ -2,22 +2,71 @@ using System; using System.Threading.Tasks; +using NetSharpExamples.Examples; namespace NetSharpExamples { internal class Program { + private static readonly INetSharpExample[] Examples = + { + // UDP socket server and client examples + new UdpSocketServerBenchmark(), + new UdpSocketServerExample(), + new UdpSocketClientSyncBenchmark(), + new UdpSocketClientAsyncBenchmark(), + new UdpSocketClientExample(), + + // TCP socket server and client examples + new TcpSocketServerBenchmark(), + new TcpSocketServerExample(), + new TcpSocketClientSyncBenchmark(), + new TcpSocketClientAsyncBenchmark(), + new TcpSocketClientExample(), + }; + private static async Task Main() { Console.WriteLine("Hello World!"); - INetSharpExample udpSocketServerBenchmark = new UdpSocketServerBenchmark(); - await udpSocketServerBenchmark.RunAsync(); + while (true) + { + PickExample(); + } + } + + private static void PickExample() + { + Console.WriteLine("Available Examples:"); + for (int i = 0; i < Examples.Length; i++) + { + Console.WriteLine($"\t{i} - {Examples[i].Name}"); + } + + while (true) + { + Console.Write("> "); + + try + { + string rawInput = Console.ReadLine(); + int choice = int.Parse(rawInput ?? "x"); + + if (0 > choice || choice >= Examples.Length) + { + Console.WriteLine("Option does not exist. Please try again!"); + continue; + } - INetSharpExample tcpSocketServerBenchmark = new TcpSocketServerBenchmark(); - await tcpSocketServerBenchmark.RunAsync(); + Examples[choice].RunAsync().GetAwaiter().GetResult(); - Console.ReadLine(); + break; + } + catch (FormatException) + { + Console.WriteLine("Invalid option selected. Please try again!"); + } + } } } } \ No newline at end of file