NetSharp

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

commit 88a598c295266260b3f6bc2a01b3715ca7ee85ef
parent aae672ae5628ea0b34921d3b4363d5f09a16c853
Author: Mikolaj Lenczewski <mikolaj.lenczewski308@gmail.com>
Date:   Tue,  9 Jun 2020 17:25:45 +0100

Redid RawStreamNetworkReader, started rework of RawStreamNetworkWriter

Diffstat:
MNetSharp/NetSharp/Raw/IRawNetworkTransportProvider.cs | 32+++++---------------------------
MNetSharp/NetSharp/Raw/Stream/RawStreamNetworkReader.cs | 170+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
MNetSharp/NetSharp/Raw/Stream/RawStreamPacket.cs | 9++++++++-
DNetSharp/NetSharp/Raw/Stream/VariablePacketRawStreamNetworkReader.cs | 180-------------------------------------------------------------------------------
ANetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkReaderBenchmark.cs | 145+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterAsyncBenchmark.cs | 131+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterSyncBenchmark.cs | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DNetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkReaderBenchmark.cs | 145-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkWriterAsyncBenchmark.cs | 131-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkWriterSyncBenchmark.cs | 135-------------------------------------------------------------------------------
ANetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkReaderExample.cs | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterAsyncExample.cs | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterSyncExample.cs | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
DNetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkReaderExample.cs | 57---------------------------------------------------------
DNetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkWriterAsyncExample.cs | 62--------------------------------------------------------------
DNetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkWriterSyncExample.cs | 64----------------------------------------------------------------
16 files changed, 709 insertions(+), 870 deletions(-)

diff --git a/NetSharp/NetSharp/Raw/IRawNetworkTransportProvider.cs b/NetSharp/NetSharp/Raw/IRawNetworkTransportProvider.cs @@ -18,11 +18,11 @@ namespace NetSharp.Raw uint preallocatedStateObjects = 0); } - public sealed class DatagramRawNetworkTransportProvider : IRawNetworkTransportProvider<RawDatagramRequestHandler> + public sealed class RawDatagramNetworkTransportProvider : IRawNetworkTransportProvider<RawDatagramRequestHandler> { private readonly ushort datagramSize; - public DatagramRawNetworkTransportProvider(ushort datagramSize) + public RawDatagramNetworkTransportProvider(ushort datagramSize) { this.datagramSize = datagramSize; } @@ -47,7 +47,7 @@ namespace NetSharp.Raw } } - public sealed class FixedPacketRawStreamNetworkTransportProvider : IRawNetworkTransportProvider<RawStreamRequestHandler> + public sealed class RawStreamNetworkTransportProvider : IRawNetworkTransportProvider<RawStreamRequestHandler> { /// <inheritdoc /> public SocketType TransportProtocolType { get; } = SocketType.Stream; @@ -56,7 +56,7 @@ namespace NetSharp.Raw public RawNetworkReaderBase GetReader(ref Socket rawConnection, EndPoint defaultEndPoint, RawStreamRequestHandler? requestHandler, int maxPooledBufferSize, int maxPooledBuffersPerBucket = 1000, uint preallocatedStateObjects = 0) { - return new FixedPacketRawStreamNetworkReader(ref rawConnection, requestHandler, defaultEndPoint, maxPooledBufferSize, + return new RawStreamNetworkReader(ref rawConnection, requestHandler, defaultEndPoint, maxPooledBufferSize, maxPooledBuffersPerBucket, preallocatedStateObjects); } @@ -64,29 +64,7 @@ namespace NetSharp.Raw public RawNetworkWriterBase GetWriter(ref Socket rawConnection, EndPoint defaultEndPoint, int maxPooledBufferSize, int maxPooledBuffersPerBucket = 1000, uint preallocatedStateObjects = 0) { - return new FixedPacketRawStreamNetworkWriter(ref rawConnection, defaultEndPoint, maxPooledBufferSize, - maxPooledBuffersPerBucket, preallocatedStateObjects); - } - } - - public sealed class VariablePacketRawStreamNetworkTransportProvider : IRawNetworkTransportProvider<RawStreamRequestHandler> - { - /// <inheritdoc /> - public SocketType TransportProtocolType { get; } = SocketType.Stream; - - /// <inheritdoc /> - public RawNetworkReaderBase GetReader(ref Socket rawConnection, EndPoint defaultEndPoint, RawStreamRequestHandler? requestHandler, - int maxPooledBufferSize, int maxPooledBuffersPerBucket = 1000, uint preallocatedStateObjects = 0) - { - return new VariablePacketRawStreamNetworkReader(ref rawConnection, requestHandler, defaultEndPoint, maxPooledBufferSize, - maxPooledBuffersPerBucket, preallocatedStateObjects); - } - - /// <inheritdoc /> - public RawNetworkWriterBase GetWriter(ref Socket rawConnection, EndPoint defaultEndPoint, int maxPooledBufferSize, - int maxPooledBuffersPerBucket = 1000, uint preallocatedStateObjects = 0) - { - return new VariablePacketRawStreamNetworkWriter(ref rawConnection, defaultEndPoint, maxPooledBufferSize, + return new RawStreamNetworkWriter(ref rawConnection, defaultEndPoint, maxPooledBufferSize, maxPooledBuffersPerBucket, preallocatedStateObjects); } } diff --git a/NetSharp/NetSharp/Raw/Stream/RawStreamNetworkReader.cs b/NetSharp/NetSharp/Raw/Stream/RawStreamNetworkReader.cs @@ -19,7 +19,7 @@ namespace NetSharp.Raw.Stream if (maxMessageSize <= 0) { throw new ArgumentOutOfRangeException(nameof(maxMessageSize), maxMessageSize, - $"The message size must be greater than 0"); + $"The maximum message size must be greater than 0"); } RequestHandler = requestHandler ?? DefaultRequestHandler; @@ -50,6 +50,11 @@ namespace NetSharp.Raw.Stream switch (args.SocketError) { case SocketError.Success: + // the buffer is set to allow a simpler ConfigureReceiveHeader() implemetation. Since returning an empty buffer is ignored in the + // array pool, this allows us to just return the last assigned buffer in the ConfigureXXX() method to the pool (this means that + // usually we will usually be returning the ResponseDataBuffer). + args.SetBuffer(Array.Empty<byte>(), 0, 0); + ConfigureReceiveHeader(args); StartReceive(args); break; @@ -66,22 +71,85 @@ namespace NetSharp.Raw.Stream { Memory<byte> headerBuffer = args.Buffer; - RawStreamPacketHeader header = RawStreamPacketHeader.Deserialise(in headerBuffer); + int receivedBytes = args.BytesTransferred, + previousReceivedBytes = args.Offset, + totalReceivedBytes = previousReceivedBytes + receivedBytes, + expectedBytes = args.Buffer.Length; + + if (totalReceivedBytes == expectedBytes) // transmission complete + { + RawStreamPacketHeader header = RawStreamPacketHeader.Deserialise(in headerBuffer); - // TODO configure the number of bytes of data to receive - ConfigureReceiveData(args, in header); - StartReceive(args); + args.UserToken = header; // allow the header to be used in the CompleteReceiveData method + + ConfigureReceiveData(args, in header); + StartReceive(args); + } + else if (0 < totalReceivedBytes && totalReceivedBytes < expectedBytes) // transmission not complete + { + args.SetBuffer(totalReceivedBytes, expectedBytes - totalReceivedBytes); + + ContinueReceive(args); + } + else if (receivedBytes == 0) // connection is dead + { + CloseClientConnection(args); + } } void CompleteReceiveData(SocketAsyncEventArgs args) { - byte[] dataBuffer = args.Buffer; + Memory<byte> dataBuffer = args.Buffer; + RawStreamPacketHeader requestPacketHeader = (RawStreamPacketHeader) args.UserToken; + + int receivedBytes = args.BytesTransferred, + previousReceivedBytes = args.Offset, + totalReceivedBytes = previousReceivedBytes + receivedBytes, + expectedBytes = args.Buffer.Length; + + if (totalReceivedBytes == expectedBytes) // transmission complete + { + EndPoint clientEndPoint = args.AcceptSocket.RemoteEndPoint; + + // TODO use user-supplied delegate to get response packet size + int responseBufferSize = RawStreamPacket.TotalPacketSize(expectedBytes); - // TODO handle request packet - //bool haveResponsePacket = RequestHandler(args.AcceptSocket.RemoteEndPoint, ); + byte[] responseBuffer = BufferPool.Rent(responseBufferSize); + + Memory<byte> responseBufferMemory = responseBuffer[RawStreamPacketHeader.TotalSize..expectedBytes]; + + // TODO rework request handler + bool responseExists = RequestHandler(clientEndPoint, dataBuffer, totalReceivedBytes, responseBufferMemory); + + switch (responseExists) + { + case true: + RawStreamPacket response = new RawStreamPacket(in responseBufferMemory); + + ConfigureSendResponse(args, ref responseBuffer, in response); + StartSend(args); + break; - ConfigureSendHeader(args); - StartSend(args); + case false: + // we manually returns the response buffer, as it wasnt set to be the args.Buffer, and since we dont have a response + // packet we can reuse it as a packet header buffer in the below ConfigureReceiveHeader() call + BufferPool.Return(responseBuffer, true); + + ConfigureReceiveHeader(args); + StartReceive(args); + break; + } + } + else if (0 < totalReceivedBytes && totalReceivedBytes < expectedBytes) // transmission not complete + { + args.SetBuffer(totalReceivedBytes, expectedBytes - totalReceivedBytes); + + ContinueReceive(args); + } + else if (receivedBytes == 0) // connection is dead + { + CloseClientConnection(args); + } } bool receivingHeader = args.Buffer.Length == RawStreamPacketHeader.TotalSize; @@ -109,37 +177,28 @@ namespace NetSharp.Raw.Stream private void CompleteSend(SocketAsyncEventArgs args) { - void CompleteSendHeader(SocketAsyncEventArgs args) - { - byte[] headerBuffer = args.Buffer; - - // TODO configure the number of bytes of data to send - ConfigureSendData(args); - StartSend(args); - } - - void CompleteSendData(SocketAsyncEventArgs args) - { - byte[] dataBuffer = args.Buffer; - - ConfigureReceiveHeader(args); - StartReceive(args); - } - - bool sendingHeader = args.Buffer.Length == RawStreamPacketHeader.TotalSize; + int sentBytes = args.BytesTransferred, + previousSentBytes = args.Offset, + totalSentBytes = previousSentBytes + sentBytes, + expectedBytes = args.Buffer.Length; switch (args.SocketError) { case SocketError.Success: - switch (sendingHeader) + if (totalSentBytes == expectedBytes) // transmission complete { - case true: - CompleteSendHeader(args); - break; + ConfigureReceiveHeader(args); + StartReceive(args); + } + else if (0 < totalSentBytes && totalSentBytes < expectedBytes) // transmission not complete + { + args.SetBuffer(totalSentBytes, expectedBytes - totalSentBytes); - case false: - CompleteSendData(args); - break; + ContinueSend(args); + } + else if (sentBytes == 0) // connection is dead + { + CloseClientConnection(args); } break; @@ -151,6 +210,8 @@ namespace NetSharp.Raw.Stream private void ConfigureReceiveData(SocketAsyncEventArgs args, in RawStreamPacketHeader receivedPacketHeader) { + BufferPool.Return(args.Buffer, true); // return and clear the requestHeaderBuffer (as it was already parsed) + byte[] pendingPacketDataBuffer = BufferPool.Rent(receivedPacketHeader.DataSize); args.SetBuffer(pendingPacketDataBuffer, 0, pendingPacketDataBuffer.Length); @@ -158,27 +219,20 @@ namespace NetSharp.Raw.Stream private void ConfigureReceiveHeader(SocketAsyncEventArgs args) { + BufferPool.Return(args.Buffer, true); // return and clear the responseDataBuffer (or requestDataBuffer if no response was generated) + byte[] pendingPacketHeaderBuffer = BufferPool.Rent(RawStreamPacketHeader.TotalSize); args.SetBuffer(pendingPacketHeaderBuffer, 0, pendingPacketHeaderBuffer.Length); } - private void ConfigureSendData(SocketAsyncEventArgs args, in RawStreamPacket pendingPacket) - { - byte[] pendingPacketDataBuffer = BufferPool.Rent(pendingPacket.Header.DataSize); - - pendingPacket.Data.CopyTo(pendingPacketDataBuffer); - - args.SetBuffer(pendingPacketDataBuffer, 0, pendingPacketDataBuffer.Length); - } - - private void ConfigureSendHeader(SocketAsyncEventArgs args, in RawStreamPacket pendingPacket) + private void ConfigureSendResponse(SocketAsyncEventArgs args, ref byte[] pendingPacketBuffer, in RawStreamPacket pendingPacket) { - byte[] pendingPacketHeaderBuffer = BufferPool.Rent(RawStreamPacketHeader.TotalSize); + BufferPool.Return(args.Buffer, true); // return and clear the requestDataBuffer (as it was already parsed) - pendingPacket.Header.Serialise(pendingPacketHeaderBuffer); + pendingPacket.Serialise(pendingPacketBuffer); - args.SetBuffer(pendingPacketHeaderBuffer, 0, pendingPacketHeaderBuffer.Length); + args.SetBuffer(pendingPacketBuffer, 0, pendingPacketBuffer.Length); } private void ContinueReceive(SocketAsyncEventArgs args) @@ -335,25 +389,5 @@ namespace NetSharp.Raw.Stream StartDefaultAccept(); } } - - private readonly struct TransmissionToken - { - public readonly int BytesTransferred; - public readonly int ExpectedBytes; - - public TransmissionToken(int expectedBytes, int bytesTransferred) - { - ExpectedBytes = expectedBytes; - - BytesTransferred = bytesTransferred; - } - - public TransmissionToken(in TransmissionToken token, int newlyTransferredBytes) - { - ExpectedBytes = token.ExpectedBytes; - - BytesTransferred = token.BytesTransferred + newlyTransferredBytes; - } - } } } \ No newline at end of file diff --git a/NetSharp/NetSharp/Raw/Stream/RawStreamPacket.cs b/NetSharp/NetSharp/Raw/Stream/RawStreamPacket.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.CompilerServices; using NetSharp.Utils.Conversion; @@ -31,11 +32,17 @@ namespace NetSharp.Raw.Stream return new RawStreamPacket(in header, in buffer); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int TotalPacketSize(int packetDataSize) + { + return RawStreamPacketHeader.TotalSize + packetDataSize; + } + public void Serialise(in Memory<byte> buffer) { Header.Serialise(buffer.Slice(0, RawStreamPacketHeader.TotalSize)); - Buffer.CopyTo(buffer.Slice(RawStreamPacketHeader.TotalSize, Data.Length)); + Data.CopyTo(buffer.Slice(RawStreamPacketHeader.TotalSize, Data.Length)); } } diff --git a/NetSharp/NetSharp/Raw/Stream/VariablePacketRawStreamNetworkReader.cs b/NetSharp/NetSharp/Raw/Stream/VariablePacketRawStreamNetworkReader.cs @@ -1,179 +0,0 @@ -namespace NetSharp.Raw.Stream -{ - /* - public sealed class VariablePacketRawStreamNetworkReader : RawStreamNetworkReader - { - /// <inheritdoc /> - public VariablePacketRawStreamNetworkReader(ref Socket rawConnection, RawStreamRequestHandler? requestHandler, EndPoint defaultEndPoint, int maxMessageSize, - int pooledBuffersPerBucket = 50, uint preallocatedStateObjects = 0) : base(ref rawConnection, requestHandler, defaultEndPoint, maxMessageSize, - pooledBuffersPerBucket, preallocatedStateObjects) - { - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ConfigureReceiveData(SocketAsyncEventArgs args, in RawStreamPacket.Header header) - { - byte[] receiveBuffer = BufferPool.Rent(header.DataSize); - args.SetBuffer(receiveBuffer, 0, header.DataSize); - - TransmissionToken token = new TransmissionToken(header.DataSize, 0); - args.UserToken = token; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ConfigureReceiveHeader(SocketAsyncEventArgs args) - { - byte[] receiveBuffer = BufferPool.Rent(RawStreamPacket.Header.TotalHeaderSize); - args.SetBuffer(receiveBuffer, 0, RawStreamPacket.Header.TotalHeaderSize); - - TransmissionToken token = new TransmissionToken(RawStreamPacket.Header.TotalHeaderSize, 0); - args.UserToken = token; - } - - /// <inheritdoc /> - protected override void CompleteAccept(SocketAsyncEventArgs args) - { - switch (args.SocketError) - { - case SocketError.Success: - ConfigureReceiveHeader(args); - - StartReceive(args); - break; - - default: - ArgsPool.Return(args); - break; - } - - StartDefaultAccept(); - } - - /// <inheritdoc /> - protected override void CompleteReceive(SocketAsyncEventArgs args) - { - TransmissionToken token = (TransmissionToken) args.UserToken; - - byte[] receiveBuffer = args.Buffer; - Memory<byte> receiveBufferMemory = new Memory<byte>(receiveBuffer); - - int expectedBytes = token.ExpectedBytes; - - bool readHeader = expectedBytes == RawStreamPacket.Header.TotalHeaderSize; - - switch (args.SocketError) - { - case SocketError.Success: - int receivedBytes = args.BytesTransferred, previousReceivedBytes = token.BytesTransferred, totalReceivedBytes = previousReceivedBytes + receivedBytes; - - if (totalReceivedBytes == expectedBytes) // transmission complete - { - if (readHeader) // handle a received message header - { - Memory<byte> headerBuffer = receiveBufferMemory.Slice(0, RawStreamPacket.Header.TotalHeaderSize); - RawStreamPacket.Header header = RawStreamPacket.Header.Deserialise(in headerBuffer); - - ConfigureReceiveData(args, in header); - - StartReceive(args); - } - else // handle a received message header - { - EndPoint clientEndPoint = args.AcceptSocket.RemoteEndPoint; - - int responseBufferSize = RawStreamPacket.Header.TotalHeaderSize + expectedBytes; - byte[] responseBuffer = BufferPool.Rent(responseBufferSize); - Memory<byte> responseBufferMemory = new Memory<byte>(responseBuffer); - - Memory<byte> headerMemory = responseBufferMemory.Slice(0, RawStreamPacket.Header.TotalHeaderSize); - Memory<byte> responseMemory = responseBufferMemory.Slice(RawStreamPacket.Header.TotalHeaderSize, expectedBytes); - - bool responseExists = RequestHandler(clientEndPoint, receiveBuffer[..expectedBytes], totalReceivedBytes, responseMemory); - BufferPool.Return(receiveBuffer, true); - - if (responseExists) - { - RawStreamPacket.Header responseHeader = new RawStreamPacket.Header(responseMemory.Length); - responseHeader.Serialise(in headerMemory); - - args.SetBuffer(responseBuffer, 0, responseBufferSize); - - TransmissionToken sendToken = new TransmissionToken(responseBufferSize, 0); - args.UserToken = sendToken; - - StartSend(args); - return; - } - - BufferPool.Return(responseBuffer, true); - - ConfigureReceiveHeader(args); - - StartReceive(args); - } - } - else if (0 < totalReceivedBytes && totalReceivedBytes < expectedBytes) // transmission not complete - { - token = new TransmissionToken(in token, receivedBytes); - args.UserToken = token; - - args.SetBuffer(totalReceivedBytes, expectedBytes - totalReceivedBytes); - - ContinueReceive(args); - } - else if (receivedBytes == 0) // connection is dead - { - CloseClientConnection(args); - } - break; - - default: - CloseClientConnection(args); - break; - } - } - - /// <inheritdoc /> - protected override void CompleteSend(SocketAsyncEventArgs args) - { - TransmissionToken token = (TransmissionToken) args.UserToken; - - byte[] sendBuffer = args.Buffer; - int expectedBytes = token.ExpectedBytes; - - switch (args.SocketError) - { - case SocketError.Success: - int sentBytes = args.BytesTransferred, previousSentBytes = token.BytesTransferred, totalSentBytes = previousSentBytes + sentBytes; - - if (totalSentBytes == expectedBytes) // transmission complete - { - BufferPool.Return(sendBuffer, true); - - ConfigureReceiveHeader(args); - - StartReceive(args); - } - else if (0 < totalSentBytes && totalSentBytes < expectedBytes) // transmission not complete - { - token = new TransmissionToken(in token, sentBytes); - args.UserToken = token; - - args.SetBuffer(totalSentBytes, expectedBytes - totalSentBytes); - - ContinueSend(args); - } - else if (sentBytes == 0) // connection is dead - { - CloseClientConnection(args); - } - break; - - default: - CloseClientConnection(args); - break; - } - } - } - */ -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkReaderBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkReaderBenchmark.cs @@ -0,0 +1,144 @@ +using System; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NetSharp.Raw.Stream; + +namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks +{ + public class StreamNetworkReaderBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000, ClientCount = 12; + + private double[] ClientBandwidths; + public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); + + public static readonly Encoding ServerEncoding = Encoding.UTF8; + public static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12373); + + public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + + /// <inheritdoc /> + public string Name { get; } = "Raw Variable Packet-size Stream Network Reader Benchmark"; + + private static bool RequestHandler(EndPoint remoteEndPoint, in ReadOnlyMemory<byte> requestBuffer, int receivedRequestBytes, + in Memory<byte> responseBuffer) + { + requestBuffer.CopyTo(responseBuffer); + + return true; + } + + 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(ClientEndPoint); + + ServerReadyEvent.Wait(); + clientSocket.Connect(ServerEndPoint); + + byte[] sendBuffer = new byte[PacketSize + RawStreamPacketHeader.TotalSize]; + byte[] receiveBuffer = new byte[PacketSize + RawStreamPacketHeader.TotalSize]; + byte[] packetBuffer = new byte[PacketSize]; + + EndPoint remoteEndPoint = ServerEndPoint; + + lock (typeof(Console)) + { + Console.WriteLine($"[Client {id}] Starting client; sending messages to {remoteEndPoint}"); + } + + for (int i = 0; i < PacketCount; i++) + { + ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})").CopyTo(packetBuffer, 0); + + RawStreamPacket streamPacket = new RawStreamPacket(packetBuffer); + streamPacket.Serialise(sendBuffer); + + benchmarkHelper.StartStopwatch(); + + int totalSent = 0; + do + { + totalSent += clientSocket.Send(sendBuffer, totalSent, sendBuffer.Length - totalSent, + SocketFlags.None); + } while (totalSent != 0 && totalSent < sendBuffer.Length); + + if (totalSent == 0) + { + break; + } + + int totalReceived = 0; + do + { + totalReceived += clientSocket.Receive(receiveBuffer, totalReceived, receiveBuffer.Length - totalReceived, + SocketFlags.None); + } while (totalReceived != 0 && totalReceived < receiveBuffer.Length); + + if (totalReceived == 0) + { + break; + } + + benchmarkHelper.StopStopwatch(); + + benchmarkHelper.SnapshotRttStats(); + } + + clientSocket.Disconnect(true); + clientSocket.Close(); + + benchmarkHelper.PrintBandwidthStats(id, PacketCount, PacketSize); + benchmarkHelper.PrintRttStats(id); + + ClientBandwidths[id] = benchmarkHelper.CalcBandwidth(PacketCount, PacketSize); + + return Task.CompletedTask; + } + + /// <inheritdoc /> + public async Task RunAsync() + { + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent per client. This could take a long time (maybe more than a minute)!"); + } + + 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); + } + + EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); + + Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + rawSocket.Bind(ServerEndPoint); + rawSocket.Listen(ClientCount); + + using RawStreamNetworkReader reader = new RawStreamNetworkReader(ref rawSocket, RequestHandler, defaultEndPoint, PacketSize); + reader.Start(ClientCount); + + ServerReadyEvent.Set(); + + await Task.WhenAll(clientTasks); + + Console.WriteLine($"Total estimated bandwidth: {ClientBandwidths.Sum():F3}"); + + reader.Stop(); + + rawSocket.Close(); + rawSocket.Dispose(); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterAsyncBenchmark.cs @@ -0,0 +1,130 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NetSharp.Raw.Stream; + +namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks +{ + public class StreamNetworkWriterAsyncBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000; + + public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); + + public static readonly Encoding ServerEncoding = StreamNetworkReaderBenchmark.ServerEncoding; + public static readonly EndPoint ServerEndPoint = StreamNetworkReaderBenchmark.ServerEndPoint; + + public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + + /// <inheritdoc /> + public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Benchmark (Asynchronous)"; + + private static Task ServerTask(CancellationToken cancellationToken) + { + using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + server.Bind(ServerEndPoint); + ServerReadyEvent.Set(); + + byte[] transmissionBuffer = new byte[PacketSize]; + + 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() + { + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent per client. This could take a long time (maybe more than a minute)!"); + } + + EndPoint defaultRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + + Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + rawSocket.Bind(ClientEndPoint); + + using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); + + ServerReadyEvent.Wait(); + rawSocket.Connect(ServerEndPoint); + + BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); + + byte[] sendBuffer = new byte[PacketSize]; + byte[] receiveBuffer = new byte[PacketSize]; + + for (int i = 0; i < PacketCount; i++) + { + byte[] packetBuffer = ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); + packetBuffer.CopyTo(sendBuffer, 0); + + benchmarkHelper.StartStopwatch(); + int sendResult = await writer.WriteAsync(ServerEndPoint, sendBuffer); + + int receiveResult = await writer.ReadAsync(ServerEndPoint, receiveBuffer); + benchmarkHelper.StopStopwatch(); + + benchmarkHelper.SnapshotRttStats(); + } + + benchmarkHelper.PrintBandwidthStats(0, PacketCount, PacketSize); + benchmarkHelper.PrintRttStats(0); + + serverCts.Cancel(); + try + { + serverTask.Dispose(); + } + catch (Exception) + { + // ignored + } + + rawSocket.Disconnect(false); + rawSocket.Shutdown(SocketShutdown.Both); + rawSocket.Close(); + rawSocket.Dispose(); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterSyncBenchmark.cs @@ -0,0 +1,134 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NetSharp.Raw.Stream; + +namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks +{ + public class StreamNetworkWriterSyncBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000; + + public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); + + public static readonly Encoding ServerEncoding = StreamNetworkReaderBenchmark.ServerEncoding; + public static readonly EndPoint ServerEndPoint = StreamNetworkReaderBenchmark.ServerEndPoint; + + public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + + /// <inheritdoc /> + public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Benchmark (Synchronous)"; + + private static Task ServerTask(CancellationToken cancellationToken) + { + using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + + server.Bind(ServerEndPoint); + ServerReadyEvent.Set(); + + byte[] transmissionBuffer = new byte[PacketSize]; + + 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 Task RunAsync() + { + if (PacketCount > 10_000) + { + Console.WriteLine($"{PacketCount} packets will be sent per client. This could take a long time (maybe more than a minute)!"); + } + + EndPoint defaultRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + + Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + rawSocket.Bind(ClientEndPoint); + + using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); + + ServerReadyEvent.Wait(); + rawSocket.Connect(ServerEndPoint); + + BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); + + byte[] sendBuffer = new byte[PacketSize]; + byte[] receiveBuffer = new byte[PacketSize]; + + EndPoint remoteEndPoint = ServerEndPoint; + + for (int i = 0; i < PacketCount; i++) + { + byte[] packetBuffer = ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); + packetBuffer.CopyTo(sendBuffer, 0); + + benchmarkHelper.StartStopwatch(); + int sendResult = writer.Write(ServerEndPoint, sendBuffer); + + int receiveResult = writer.Read(ref remoteEndPoint, receiveBuffer); + benchmarkHelper.StopStopwatch(); + + benchmarkHelper.SnapshotRttStats(); + } + + benchmarkHelper.PrintBandwidthStats(0, PacketCount, PacketSize); + benchmarkHelper.PrintRttStats(0); + + serverCts.Cancel(); + try + { + serverTask.Dispose(); + } + catch (Exception) + { + // ignored + } + + rawSocket.Disconnect(false); + rawSocket.Shutdown(SocketShutdown.Both); + rawSocket.Close(); + rawSocket.Dispose(); + + return Task.CompletedTask; + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkReaderBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkReaderBenchmark.cs @@ -1,144 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks -{ - public class VariablePacketStreamNetworkReaderBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000, ClientCount = 12; - - private double[] ClientBandwidths; - public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - - public static readonly Encoding ServerEncoding = Encoding.UTF8; - public static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12373); - - public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw Variable Packet-size Stream Network Reader Benchmark"; - - private static bool RequestHandler(EndPoint remoteEndPoint, in ReadOnlyMemory<byte> requestBuffer, int receivedRequestBytes, - in Memory<byte> responseBuffer) - { - requestBuffer.CopyTo(responseBuffer); - - return true; - } - - 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(ClientEndPoint); - - ServerReadyEvent.Wait(); - clientSocket.Connect(ServerEndPoint); - - byte[] sendBuffer = new byte[PacketSize + RawStreamPacket.Header.TotalHeaderSize]; - byte[] receiveBuffer = new byte[PacketSize + RawStreamPacket.Header.TotalHeaderSize]; - byte[] packetBuffer = new byte[PacketSize]; - - EndPoint remoteEndPoint = ServerEndPoint; - - lock (typeof(Console)) - { - Console.WriteLine($"[Client {id}] Starting client; sending messages to {remoteEndPoint}"); - } - - for (int i = 0; i < PacketCount; i++) - { - ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})").CopyTo(packetBuffer, 0); - - RawStreamPacket streamPacket = new RawStreamPacket(packetBuffer); - streamPacket.Serialise(sendBuffer); - - benchmarkHelper.StartStopwatch(); - - int totalSent = 0; - do - { - totalSent += clientSocket.Send(sendBuffer, totalSent, sendBuffer.Length - totalSent, - SocketFlags.None); - } while (totalSent != 0 && totalSent < sendBuffer.Length); - - if (totalSent == 0) - { - break; - } - - int totalReceived = 0; - do - { - totalReceived += clientSocket.Receive(receiveBuffer, totalReceived, receiveBuffer.Length - totalReceived, - SocketFlags.None); - } while (totalReceived != 0 && totalReceived < receiveBuffer.Length); - - if (totalReceived == 0) - { - break; - } - - benchmarkHelper.StopStopwatch(); - - benchmarkHelper.SnapshotRttStats(); - } - - clientSocket.Disconnect(true); - clientSocket.Close(); - - benchmarkHelper.PrintBandwidthStats(id, PacketCount, PacketSize); - benchmarkHelper.PrintRttStats(id); - - ClientBandwidths[id] = benchmarkHelper.CalcBandwidth(PacketCount, PacketSize); - - return Task.CompletedTask; - } - - /// <inheritdoc /> - public async Task RunAsync() - { - if (PacketCount > 10_000) - { - Console.WriteLine($"{PacketCount} packets will be sent per client. This could take a long time (maybe more than a minute)!"); - } - - 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); - } - - EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); - - Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - rawSocket.Bind(ServerEndPoint); - rawSocket.Listen(ClientCount); - - using RawStreamNetworkReader reader = new VariablePacketRawStreamNetworkReader(ref rawSocket, RequestHandler, defaultEndPoint, PacketSize); - reader.Start(ClientCount); - - ServerReadyEvent.Set(); - - await Task.WhenAll(clientTasks); - - Console.WriteLine($"Total estimated bandwidth: {ClientBandwidths.Sum():F3}"); - - reader.Stop(); - - rawSocket.Close(); - rawSocket.Dispose(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkWriterAsyncBenchmark.cs @@ -1,130 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks -{ - public class VariablePacketStreamNetworkWriterAsyncBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000; - - public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - - public static readonly Encoding ServerEncoding = VariablePacketStreamNetworkReaderBenchmark.ServerEncoding; - public static readonly EndPoint ServerEndPoint = VariablePacketStreamNetworkReaderBenchmark.ServerEndPoint; - - public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Benchmark (Asynchronous)"; - - private static Task ServerTask(CancellationToken cancellationToken) - { - using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - - server.Bind(ServerEndPoint); - ServerReadyEvent.Set(); - - byte[] transmissionBuffer = new byte[PacketSize]; - - 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() - { - if (PacketCount > 10_000) - { - Console.WriteLine($"{PacketCount} packets will be sent per client. This could take a long time (maybe more than a minute)!"); - } - - EndPoint defaultRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - - Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - rawSocket.Bind(ClientEndPoint); - - using RawStreamNetworkWriter writer = new VariablePacketRawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); - - using CancellationTokenSource serverCts = new CancellationTokenSource(); - Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); - - ServerReadyEvent.Wait(); - rawSocket.Connect(ServerEndPoint); - - BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); - - byte[] sendBuffer = new byte[PacketSize]; - byte[] receiveBuffer = new byte[PacketSize]; - - for (int i = 0; i < PacketCount; i++) - { - byte[] packetBuffer = ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); - packetBuffer.CopyTo(sendBuffer, 0); - - benchmarkHelper.StartStopwatch(); - int sendResult = await writer.WriteAsync(ServerEndPoint, sendBuffer); - - int receiveResult = await writer.ReadAsync(ServerEndPoint, receiveBuffer); - benchmarkHelper.StopStopwatch(); - - benchmarkHelper.SnapshotRttStats(); - } - - benchmarkHelper.PrintBandwidthStats(0, PacketCount, PacketSize); - benchmarkHelper.PrintRttStats(0); - - serverCts.Cancel(); - try - { - serverTask.Dispose(); - } - catch (Exception) - { - // ignored - } - - rawSocket.Disconnect(false); - rawSocket.Shutdown(SocketShutdown.Both); - rawSocket.Close(); - rawSocket.Dispose(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/VariablePacketStreamNetworkWriterSyncBenchmark.cs @@ -1,134 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks -{ - public class VariablePacketStreamNetworkWriterSyncBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000; - - public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - - public static readonly Encoding ServerEncoding = VariablePacketStreamNetworkReaderBenchmark.ServerEncoding; - public static readonly EndPoint ServerEndPoint = VariablePacketStreamNetworkReaderBenchmark.ServerEndPoint; - - public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Benchmark (Synchronous)"; - - private static Task ServerTask(CancellationToken cancellationToken) - { - using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - - server.Bind(ServerEndPoint); - ServerReadyEvent.Set(); - - byte[] transmissionBuffer = new byte[PacketSize]; - - 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 Task RunAsync() - { - if (PacketCount > 10_000) - { - Console.WriteLine($"{PacketCount} packets will be sent per client. This could take a long time (maybe more than a minute)!"); - } - - EndPoint defaultRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - - Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - rawSocket.Bind(ClientEndPoint); - - using RawStreamNetworkWriter writer = new VariablePacketRawStreamNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); - - using CancellationTokenSource serverCts = new CancellationTokenSource(); - Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); - - ServerReadyEvent.Wait(); - rawSocket.Connect(ServerEndPoint); - - BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); - - byte[] sendBuffer = new byte[PacketSize]; - byte[] receiveBuffer = new byte[PacketSize]; - - EndPoint remoteEndPoint = ServerEndPoint; - - for (int i = 0; i < PacketCount; i++) - { - byte[] packetBuffer = ServerEncoding.GetBytes($"[Client 0] Hello World! (Packet {i})"); - packetBuffer.CopyTo(sendBuffer, 0); - - benchmarkHelper.StartStopwatch(); - int sendResult = writer.Write(ServerEndPoint, sendBuffer); - - int receiveResult = writer.Read(ref remoteEndPoint, receiveBuffer); - benchmarkHelper.StopStopwatch(); - - benchmarkHelper.SnapshotRttStats(); - } - - benchmarkHelper.PrintBandwidthStats(0, PacketCount, PacketSize); - benchmarkHelper.PrintRttStats(0); - - serverCts.Cancel(); - try - { - serverTask.Dispose(); - } - catch (Exception) - { - // ignored - } - - rawSocket.Disconnect(false); - rawSocket.Shutdown(SocketShutdown.Both); - rawSocket.Close(); - rawSocket.Dispose(); - - return Task.CompletedTask; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkReaderExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkReaderExample.cs @@ -0,0 +1,56 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +using NetSharp.Raw.Stream; + +namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples +{ + public class StreamNetworkReaderExample : INetSharpExample + { + private const int PacketSize = 8192, ExpectedClientCount = 8; + public static readonly Encoding ServerEncoding = Encoding.UTF8; + public static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12377); + + /// <inheritdoc /> + public string Name { get; } = "Raw Variable Packet-size Stream Network Reader Example"; + + private static bool RequestHandler(EndPoint remoteEndPoint, in ReadOnlyMemory<byte> requestBuffer, int receivedRequestBytes, + in Memory<byte> responseBuffer) + { + requestBuffer.CopyTo(responseBuffer); + + lock (typeof(Console)) + { + Console.WriteLine($"Received {receivedRequestBytes} bytes from {remoteEndPoint}! Echoing back..."); + } + + return true; + } + + /// <inheritdoc /> + public Task RunAsync() + { + EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); + + Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + rawSocket.Bind(ServerEndPoint); + rawSocket.Listen(ExpectedClientCount); + + using RawStreamNetworkReader reader = new RawStreamNetworkReader(ref rawSocket, RequestHandler, defaultEndPoint, PacketSize, 100); + reader.Start(ExpectedClientCount); + + Console.WriteLine($"Started stream server at {ServerEndPoint}! Enter any key to stop the server..."); + Console.ReadLine(); + + reader.Stop(); + + rawSocket.Close(); + rawSocket.Dispose(); + + return Task.CompletedTask; + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterAsyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterAsyncExample.cs @@ -0,0 +1,61 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +using NetSharp.Raw.Stream; + +namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples +{ + public class StreamNetworkWriterAsyncExample : INetSharpExample + { + private const int PacketSize = 8192; + + public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); + + public static readonly Encoding ServerEncoding = StreamNetworkReaderExample.ServerEncoding; + public static readonly EndPoint ServerEndPoint = StreamNetworkReaderExample.ServerEndPoint; + + /// <inheritdoc /> + public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Example (Asynchronous)"; + + /// <inheritdoc /> + public async Task RunAsync() + { + EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); + + Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + rawSocket.Bind(ClientEndPoint); + + using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultEndPoint, PacketSize); + await writer.ConnectAsync(ServerEndPoint); + + byte[] transmissionBuffer = new byte[PacketSize]; + + EndPoint remoteEndPoint = ServerEndPoint; + + while (true) + { + int sent = await writer.WriteAsync(remoteEndPoint, transmissionBuffer); + + lock (typeof(Console)) + { + Console.WriteLine($"Sent {sent} bytes to {remoteEndPoint}!"); + } + + int received = await writer.ReadAsync(remoteEndPoint, transmissionBuffer); + + lock (typeof(Console)) + { + Console.WriteLine($"Received {received} bytes from {remoteEndPoint}!"); + } + } + + await writer.DisconnectAsync(false); + + rawSocket.Close(); + rawSocket.Dispose(); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterSyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterSyncExample.cs @@ -0,0 +1,63 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading.Tasks; + +using NetSharp.Raw.Stream; + +namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples +{ + public class StreamNetworkWriterSyncExample : INetSharpExample + { + private const int PacketSize = 8192; + + public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); + + public static readonly Encoding ServerEncoding = StreamNetworkReaderExample.ServerEncoding; + public static readonly EndPoint ServerEndPoint = StreamNetworkReaderExample.ServerEndPoint; + + /// <inheritdoc /> + public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Example (Synchronous)"; + + /// <inheritdoc /> + public Task RunAsync() + { + EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); + + Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + rawSocket.Bind(ClientEndPoint); + + using RawStreamNetworkWriter writer = new RawStreamNetworkWriter(ref rawSocket, defaultEndPoint, PacketSize); + writer.Connect(ServerEndPoint); + + byte[] transmissionBuffer = new byte[PacketSize]; + + EndPoint remoteEndPoint = ServerEndPoint; + + while (true) + { + int sent = writer.Write(remoteEndPoint, transmissionBuffer); + + lock (typeof(Console)) + { + Console.WriteLine($"Sent {sent} bytes to {remoteEndPoint}!"); + } + + int received = writer.Read(ref remoteEndPoint, transmissionBuffer); + + lock (typeof(Console)) + { + Console.WriteLine($"Received {received} bytes from {remoteEndPoint}!"); + } + } + + writer.Disconnect(false); + + rawSocket.Close(); + rawSocket.Dispose(); + + return Task.CompletedTask; + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkReaderExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkReaderExample.cs @@ -1,56 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; - -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples -{ - public class VariablePacketStreamNetworkReaderExample : INetSharpExample - { - private const int PacketSize = 8192, ExpectedClientCount = 8; - public static readonly Encoding ServerEncoding = Encoding.UTF8; - public static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12377); - - /// <inheritdoc /> - public string Name { get; } = "Raw Variable Packet-size Stream Network Reader Example"; - - private static bool RequestHandler(EndPoint remoteEndPoint, in ReadOnlyMemory<byte> requestBuffer, int receivedRequestBytes, - in Memory<byte> responseBuffer) - { - requestBuffer.CopyTo(responseBuffer); - - lock (typeof(Console)) - { - Console.WriteLine($"Received {receivedRequestBytes} bytes from {remoteEndPoint}! Echoing back..."); - } - - return true; - } - - /// <inheritdoc /> - public Task RunAsync() - { - EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); - - Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - rawSocket.Bind(ServerEndPoint); - rawSocket.Listen(ExpectedClientCount); - - using RawStreamNetworkReader reader = new VariablePacketRawStreamNetworkReader(ref rawSocket, RequestHandler, defaultEndPoint, PacketSize, 100); - reader.Start(ExpectedClientCount); - - Console.WriteLine($"Started stream server at {ServerEndPoint}! Enter any key to stop the server..."); - Console.ReadLine(); - - reader.Stop(); - - rawSocket.Close(); - rawSocket.Dispose(); - - return Task.CompletedTask; - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkWriterAsyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkWriterAsyncExample.cs @@ -1,61 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; - -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples -{ - public class VariablePacketStreamNetworkWriterAsyncExample : INetSharpExample - { - private const int PacketSize = 8192; - - public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - - public static readonly Encoding ServerEncoding = VariablePacketStreamNetworkReaderExample.ServerEncoding; - public static readonly EndPoint ServerEndPoint = VariablePacketStreamNetworkReaderExample.ServerEndPoint; - - /// <inheritdoc /> - public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Example (Asynchronous)"; - - /// <inheritdoc /> - public async Task RunAsync() - { - EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); - - Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - rawSocket.Bind(ClientEndPoint); - - using RawStreamNetworkWriter writer = new VariablePacketRawStreamNetworkWriter(ref rawSocket, defaultEndPoint, PacketSize); - await writer.ConnectAsync(ServerEndPoint); - - byte[] transmissionBuffer = new byte[PacketSize]; - - EndPoint remoteEndPoint = ServerEndPoint; - - while (true) - { - int sent = await writer.WriteAsync(remoteEndPoint, transmissionBuffer); - - lock (typeof(Console)) - { - Console.WriteLine($"Sent {sent} bytes to {remoteEndPoint}!"); - } - - int received = await writer.ReadAsync(remoteEndPoint, transmissionBuffer); - - lock (typeof(Console)) - { - Console.WriteLine($"Received {received} bytes from {remoteEndPoint}!"); - } - } - - await writer.DisconnectAsync(false); - - rawSocket.Close(); - rawSocket.Dispose(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkWriterSyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/VariablePacketStreamNetworkWriterSyncExample.cs @@ -1,63 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading.Tasks; - -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples -{ - public class VariablePacketStreamNetworkWriterSyncExample : INetSharpExample - { - private const int PacketSize = 8192; - - public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - - public static readonly Encoding ServerEncoding = VariablePacketStreamNetworkReaderExample.ServerEncoding; - public static readonly EndPoint ServerEndPoint = VariablePacketStreamNetworkReaderExample.ServerEndPoint; - - /// <inheritdoc /> - public string Name { get; } = "Raw Variable Packet-size Stream Network Writer Example (Synchronous)"; - - /// <inheritdoc /> - public Task RunAsync() - { - EndPoint defaultEndPoint = new IPEndPoint(IPAddress.Any, 0); - - Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); - rawSocket.Bind(ClientEndPoint); - - using RawStreamNetworkWriter writer = new VariablePacketRawStreamNetworkWriter(ref rawSocket, defaultEndPoint, PacketSize); - writer.Connect(ServerEndPoint); - - byte[] transmissionBuffer = new byte[PacketSize]; - - EndPoint remoteEndPoint = ServerEndPoint; - - while (true) - { - int sent = writer.Write(remoteEndPoint, transmissionBuffer); - - lock (typeof(Console)) - { - Console.WriteLine($"Sent {sent} bytes to {remoteEndPoint}!"); - } - - int received = writer.Read(ref remoteEndPoint, transmissionBuffer); - - lock (typeof(Console)) - { - Console.WriteLine($"Received {received} bytes from {remoteEndPoint}!"); - } - } - - writer.Disconnect(false); - - rawSocket.Close(); - rawSocket.Dispose(); - - return Task.CompletedTask; - } - } -} -\ No newline at end of file