NetSharp

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

commit e5205a37ab7b580e45e1b8a9711cc08abb371b51
parent 154bc85f470fcdafe397282984268e3547a17859
Author: Mikolaj Lenczewski <mikolaj.lenczewski308@gmail.com>
Date:   Sat, 13 Jun 2020 18:33:30 +0100

Reorganised 'Examples' project into separate NetSharp.Tests, NetSharp.Examples, and NetSharp.Benchmarks projects

Diffstat:
ANetSharp/NetSharp.Benchmarks/BenchmarkHelper.cs | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkReaderBenchmark.cs | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterAsyncBenchmark.cs | 103+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterSyncBenchmark.cs | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkReaderBenchmark.cs | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterAsyncBenchmark.cs | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterSyncBenchmark.cs | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/INetSharpBenchmark.cs | 21+++++++++++++++++++++
ANetSharp/NetSharp.Benchmarks/NetSharp.Benchmarks.csproj | 12++++++++++++
ANetSharp/NetSharp.Benchmarks/Program.cs | 117+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ANetSharp/NetSharp.Tests/NetSharp.Tests.csproj | 12++++++++++++
ANetSharp/NetSharp.Tests/Program.cs | 24++++++++++++++++++++++++
MNetSharp/NetSharp.sln | 14+++++++++++++-
MNetSharp/NetSharp/AssemblyAttributes.cs | 2+-
DNetSharp/NetSharp/INetworkReader.cs | 10----------
DNetSharp/NetSharp/INetworkWriter.cs | 23-----------------------
ANetSharp/NetSharp/Interfaces/INetworkReader.cs | 10++++++++++
ANetSharp/NetSharp/Interfaces/INetworkWriter.cs | 23+++++++++++++++++++++++
MNetSharp/NetSharp/Raw/RawNetworkReaderBase.cs | 2++
MNetSharp/NetSharp/Raw/RawNetworkWriterBase.cs | 2++
DNetSharp/NetSharpExamples/BenchmarkHelper.cs | 96-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkReaderBenchmark.cs | 119-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterAsyncBenchmark.cs | 103-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterSyncBenchmark.cs | 99-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkReaderBenchmark.cs | 143-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterAsyncBenchmark.cs | 130-------------------------------------------------------------------------------
DNetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterSyncBenchmark.cs | 135-------------------------------------------------------------------------------
MNetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkReaderExample.cs | 2+-
MNetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkWriterAsyncExample.cs | 2+-
MNetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkWriterSyncExample.cs | 2+-
MNetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/RawStreamChatServer.cs | 2+-
MNetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkReaderExample.cs | 2+-
MNetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterAsyncExample.cs | 2+-
MNetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterSyncExample.cs | 2+-
DNetSharp/NetSharpExamples/INetSharpBenchmark.cs | 7-------
MNetSharp/NetSharpExamples/INetSharpExample.cs | 2+-
RNetSharp/NetSharpExamples/NetSharpExamples.csproj -> NetSharp/NetSharpExamples/NetSharp.Examples.csproj | 0
MNetSharp/NetSharpExamples/NetSharpExamples.xml | 68++++++++++++++++----------------------------------------------------
MNetSharp/NetSharpExamples/Program.cs | 46++++++----------------------------------------
39 files changed, 1092 insertions(+), 967 deletions(-)

diff --git a/NetSharp/NetSharp.Benchmarks/BenchmarkHelper.cs b/NetSharp/NetSharp.Benchmarks/BenchmarkHelper.cs @@ -0,0 +1,95 @@ +using System; +using System.Diagnostics; + +namespace NetSharp.Benchmarks +{ + public sealed class BenchmarkHelper + { + private readonly Stopwatch stopwatch = new Stopwatch(); + private long lastTicksSnapshot = 0, lastMsSnapshot = 0; + private long minRttMs = int.MaxValue, maxRttMs = int.MinValue; + private long minRttTicks = int.MaxValue, maxRttTicks = int.MinValue; + + public BenchmarkHelper() + { + stopwatch.Reset(); + } + + public long RttMs => stopwatch.ElapsedMilliseconds; + + public long RttTicks => stopwatch.ElapsedTicks; + + public double CalcBandwidth(long sentPacketCount, long packetSize) + { + long millis = stopwatch.ElapsedMilliseconds; + double megabytes = sentPacketCount * packetSize / 1_000_000.0; + double bandwidth = megabytes / (millis / 1000.0); + + return bandwidth; + } + + public void PrintBandwidthStats(int clientId, long sentPacketCount, long packetSize) + { + long millis = stopwatch.ElapsedMilliseconds; + double megabytes = sentPacketCount * packetSize / 1_000_000.0; + double bandwidth = megabytes / (millis / 1000.0); + + lock (typeof(Console)) + { + Console.WriteLine($"[Client {clientId}] Sent {sentPacketCount} packets (of size {packetSize} bytes; {megabytes / 1000} gigabytes [one-way]) in {millis} milliseconds"); + Console.WriteLine($"[Client {clientId}] Approximate bandwidth: {bandwidth:F3} MBps"); + } + } + + public void PrintRttStats(int clientId) + { + lock (typeof(Console)) + { + Console.WriteLine($"[Client {clientId}] Min RTT: {minRttTicks} ticks, {minRttMs} ms"); + Console.WriteLine($"[Client {clientId}] Max RTT: {maxRttTicks} ticks, {maxRttMs} ms"); + } + } + + public void ResetStopwatch() + { + lastTicksSnapshot = 0; + lastMsSnapshot = 0; + + stopwatch.Reset(); + } + + public void SnapshotRttStats() + { + long elapsedTicksSnapshot = stopwatch.ElapsedTicks, elapsedMsSnapshot = stopwatch.ElapsedMilliseconds; + + minRttTicks = elapsedTicksSnapshot - lastTicksSnapshot < minRttTicks + ? elapsedTicksSnapshot - lastTicksSnapshot + : minRttTicks; + + minRttMs = elapsedMsSnapshot - lastMsSnapshot < minRttMs + ? elapsedMsSnapshot - lastMsSnapshot + : minRttMs; + + maxRttTicks = elapsedTicksSnapshot - lastTicksSnapshot > maxRttTicks + ? elapsedTicksSnapshot - lastTicksSnapshot + : maxRttTicks; + + maxRttMs = elapsedMsSnapshot - lastMsSnapshot > maxRttMs + ? elapsedMsSnapshot - lastMsSnapshot + : maxRttMs; + + lastTicksSnapshot = elapsedTicksSnapshot; + lastMsSnapshot = elapsedMsSnapshot; + } + + public void StartStopwatch() + { + stopwatch.Start(); + } + + public void StopStopwatch() + { + stopwatch.Stop(); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkReaderBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkReaderBenchmark.cs @@ -0,0 +1,118 @@ +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.Datagram; + +namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks +{ + internal class DatagramNetworkReaderBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000, ClientCount = 12; + private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; + private static readonly Encoding ServerEncoding = Program.DefaultEncoding; + private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; + private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + private double[] ClientBandwidths; + + /// <inheritdoc /> + public string Name { get; } = "Raw Datagram 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) + { + try + { + int id = (int) idObj; + + BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); + + Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + clientSocket.Bind(ClientEndPoint); + + ServerReadyEvent.Wait(); + + byte[] sendBuffer = new byte[PacketSize]; + byte[] receiveBuffer = 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++) + { + byte[] packetBuffer = ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})"); + packetBuffer.CopyTo(sendBuffer, 0); + + benchmarkHelper.StartStopwatch(); + int sentBytes = clientSocket.SendTo(sendBuffer, remoteEndPoint); + + int receivedBytes = clientSocket.ReceiveFrom(receiveBuffer, ref remoteEndPoint); + benchmarkHelper.StopStopwatch(); + + benchmarkHelper.SnapshotRttStats(); + } + + benchmarkHelper.PrintBandwidthStats(id, PacketCount, PacketSize); + benchmarkHelper.PrintRttStats(id); + + ClientBandwidths[id] = benchmarkHelper.CalcBandwidth(PacketCount, PacketSize); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + + 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 defaultRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + + Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + rawSocket.Bind(ServerEndPoint); + + using RawDatagramNetworkReader reader = new RawDatagramNetworkReader(ref rawSocket, RequestHandler, defaultRemoteEndPoint, PacketSize); + reader.Start(ClientCount); + + ServerReadyEvent.Set(); + + await Task.WhenAll(clientTasks); + + Console.WriteLine($"Total estimated bandwidth: {ClientBandwidths.Sum():F3}"); + + reader.Shutdown(); + + rawSocket.Close(); + rawSocket.Dispose(); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterAsyncBenchmark.cs @@ -0,0 +1,102 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NetSharp.Raw.Datagram; + +namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks +{ + internal class DatagramNetworkWriterAsyncBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000; + private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; + private static readonly Encoding ServerEncoding = Program.DefaultEncoding; + private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; + private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + + /// <inheritdoc /> + public string Name { get; } = "Raw Datagram Network Writer Benchmark (Asynchronous)"; + + private static Task ServerTask(CancellationToken cancellationToken) + { + using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + server.Bind(ServerEndPoint); + ServerReadyEvent.Set(); + + byte[] transmissionBuffer = new byte[PacketSize]; + + 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() + { + 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.Dgram, ProtocolType.Udp); + rawSocket.Bind(ClientEndPoint); + + using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); + + ServerReadyEvent.Wait(); + + 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.Close(); + rawSocket.Dispose(); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterSyncBenchmark.cs @@ -0,0 +1,98 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NetSharp.Raw.Datagram; + +namespace NetSharp.Benchmarks.Benchmarks.Datagram_Network_Connection_Benchmarks +{ + internal class DatagramNetworkWriterSyncBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000; + private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; + private static readonly Encoding ServerEncoding = Program.DefaultEncoding; + private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; + private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + + /// <inheritdoc /> + public string Name { get; } = "Raw Datagram Network Writer Benchmark (Synchronous)"; + + private static Task ServerTask(CancellationToken cancellationToken) + { + using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + + server.Bind(ServerEndPoint); + ServerReadyEvent.Set(); + + byte[] transmissionBuffer = new byte[PacketSize]; + + EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); + + while (!cancellationToken.IsCancellationRequested) + { + int received = server.ReceiveFrom(transmissionBuffer, ref remoteEndPoint); + + int sent = server.SendTo(transmissionBuffer, remoteEndPoint); + } + + 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.Dgram, ProtocolType.Udp); + rawSocket.Bind(ClientEndPoint); + + using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); + + using CancellationTokenSource serverCts = new CancellationTokenSource(); + Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); + + ServerReadyEvent.Wait(); + + 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(); + + rawSocket.Close(); + rawSocket.Dispose(); + + return Task.CompletedTask; + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkReaderBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkReaderBenchmark.cs @@ -0,0 +1,142 @@ +using System; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NetSharp.Packets; +using NetSharp.Raw.Stream; + +namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks +{ + internal class StreamNetworkReaderBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000, ClientCount = 12; + private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; + private static readonly Encoding ServerEncoding = Program.DefaultEncoding; + private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; + private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + private double[] ClientBandwidths; + + /// <inheritdoc /> + public string Name { get; } = "Raw 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); + + RawStreamPacketHeader streamPacketHeader = new RawStreamPacketHeader(PacketSize); + RawStreamPacket.Serialise(sendBuffer, in streamPacketHeader, packetBuffer); + + 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.Shutdown(); + + rawSocket.Close(); + rawSocket.Dispose(); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterAsyncBenchmark.cs @@ -0,0 +1,129 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +using NetSharp.Packets; +using NetSharp.Raw.Stream; + +namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks +{ + internal class StreamNetworkWriterAsyncBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000; + private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; + private static readonly Encoding ServerEncoding = Program.DefaultEncoding; + private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; + private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + + /// <inheritdoc /> + public string Name { get; } = "Raw 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(); + + RawStreamPacketHeader archetypalHeader = new RawStreamPacketHeader(PacketSize); + byte[] transmissionBuffer = new byte[RawStreamPacket.TotalPacketSize(in archetypalHeader)]; + + 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/NetSharp.Benchmarks/Benchmarks/Stream Network Connection Benchmarks/StreamNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharp.Benchmarks/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.Packets; +using NetSharp.Raw.Stream; + +namespace NetSharp.Benchmarks.Benchmarks.Stream_Network_Connection_Benchmarks +{ + internal class StreamNetworkWriterSyncBenchmark : INetSharpBenchmark + { + private const int PacketSize = 8192, PacketCount = 1_000_000; + private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; + private static readonly Encoding ServerEncoding = Program.DefaultEncoding; + private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; + private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); + + /// <inheritdoc /> + public string Name { get; } = "Raw 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(); + + // all the headers should have the same packet size, so will fit in the transmission buffer + RawStreamPacketHeader archetypalHeader = new RawStreamPacketHeader(PacketSize); + byte[] transmissionBuffer = new byte[RawStreamPacket.TotalPacketSize(in archetypalHeader)]; + + 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 < expectedBytes && receivedBytes > 0); + + if (receivedBytes == 0) + { + break; + } + + int sentBytes = 0; + do + { + sentBytes += clientSocket.Send(transmissionBuffer, sentBytes, expectedBytes - sentBytes, SocketFlags.None); + } while (sentBytes < expectedBytes && sentBytes > 0); + + 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/NetSharp.Benchmarks/INetSharpBenchmark.cs b/NetSharp/NetSharp.Benchmarks/INetSharpBenchmark.cs @@ -0,0 +1,20 @@ +using System.Threading.Tasks; + +namespace NetSharp.Benchmarks +{ + /// <summary> + /// Defines a benchmark program. + /// </summary> + public interface INetSharpBenchmark + { + /// <summary> + /// The name of the benchmark. + /// </summary> + string Name { get; } + + /// <summary> + /// Runs the benchmark asynchronously. + /// </summary> + Task RunAsync(); + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.Benchmarks/NetSharp.Benchmarks.csproj b/NetSharp/NetSharp.Benchmarks/NetSharp.Benchmarks.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>netcoreapp3.1</TargetFramework> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\NetSharp\NetSharp.csproj" /> + </ItemGroup> + +</Project> diff --git a/NetSharp/NetSharp.Benchmarks/Program.cs b/NetSharp/NetSharp.Benchmarks/Program.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Reflection; +using System.Resources; +using System.Text; + +[assembly: NeutralResourcesLanguage("en")] + +namespace NetSharp.Benchmarks +{ + internal class Program + { + private const int DefaultExamplePort = 44231; + private static readonly List<INetSharpBenchmark> Benchmarks; + private static readonly IPAddress DefaultExampleAddress = IPAddress.Loopback; + public static readonly EndPoint DefaultClientEndPoint = new IPEndPoint(DefaultExampleAddress, 0); + public static readonly Encoding DefaultEncoding = Encoding.UTF8; + public static readonly EndPoint DefaultServerEndPoint = new IPEndPoint(DefaultExampleAddress, DefaultExamplePort); + + static Program() + { + Benchmarks = new List<INetSharpBenchmark>(); + + foreach (Type type in Assembly.GetCallingAssembly().GetTypes()) + { + if (!type.IsClass && !type.IsValueType) + { + continue; + } + + Type[] interfaces = type.GetInterfaces(); + object instance = Activator.CreateInstance(type); + + if (type.GetInterface(nameof(INetSharpBenchmark)) == typeof(INetSharpBenchmark)) + { + Benchmarks.Add((INetSharpBenchmark) instance); + } + } + } + + private static void Main() + { + RunAllBenchmarks(); + + while (true) + { + GC.Collect(); + + PickBenchmark(); + } + } + + private static void PickBenchmark() + { + Console.WriteLine("Available Examples:"); + for (int i = 0; i < Benchmarks.Count; i++) + { + Console.WriteLine($"\t{i:D2} - {Benchmarks[i].Name}"); + } + + while (true) + { + Console.Write("> "); + + try + { + string rawInput = Console.ReadLine(); + int choice = int.Parse(rawInput ?? "x"); + + if (choice < 0 || choice >= Benchmarks.Count) + { + Console.WriteLine("Option does not exist. Please try again!"); + continue; + } + + INetSharpBenchmark selectedExample = Benchmarks[choice]; + + Console.WriteLine($"Starting \'{selectedExample.Name}\'..."); + selectedExample.RunAsync().GetAwaiter().GetResult(); + Console.WriteLine($"Finished \'{selectedExample.Name}\'!"); + + break; + } + catch (FormatException) + { + Console.WriteLine("Invalid option selected. Please try again!"); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + + Console.WriteLine(); + } + + private static void RunAllBenchmarks() + { + Console.WriteLine("Run all benchmarks? (y/n)"); + string input = Console.ReadLine()?.ToLowerInvariant() ?? "n"; + + if (input == "y") + { + foreach (INetSharpBenchmark benchmark in Benchmarks) + { + Console.WriteLine($"Starting \'{benchmark.Name}\'..."); + benchmark.RunAsync().GetAwaiter().GetResult(); + Console.WriteLine($"Finished \'{benchmark.Name}\'!"); + + Console.WriteLine(); + } + } + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.Tests/NetSharp.Tests.csproj b/NetSharp/NetSharp.Tests/NetSharp.Tests.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <TargetFramework>netcoreapp3.1</TargetFramework> + </PropertyGroup> + + <ItemGroup> + <ProjectReference Include="..\NetSharp\NetSharp.csproj" /> + </ItemGroup> + +</Project> diff --git a/NetSharp/NetSharp.Tests/Program.cs b/NetSharp/NetSharp.Tests/Program.cs @@ -0,0 +1,23 @@ +using System; +using System.Net; +using System.Resources; +using System.Text; + +[assembly: NeutralResourcesLanguage("en")] + +namespace NetSharp.Tests +{ + internal class Program + { + private const int DefaultExamplePort = 44232; + private static readonly IPAddress DefaultExampleAddress = IPAddress.Loopback; + public static readonly EndPoint DefaultClientEndPoint = new IPEndPoint(DefaultExampleAddress, 0); + public static readonly Encoding DefaultEncoding = Encoding.UTF8; + public static readonly EndPoint DefaultServerEndPoint = new IPEndPoint(DefaultExampleAddress, DefaultExamplePort); + + private static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp.sln b/NetSharp/NetSharp.sln @@ -5,7 +5,7 @@ VisualStudioVersion = 16.0.29324.140 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetSharp", "NetSharp\NetSharp.csproj", "{424A38DB-7CA0-4C94-90B4-EF246CB4BDC4}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetSharpExamples", "NetSharpExamples\NetSharpExamples.csproj", "{5861E518-E712-4031-9AA1-0313736FF957}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetSharp.Examples", "NetSharpExamples\NetSharp.Examples.csproj", "{5861E518-E712-4031-9AA1-0313736FF957}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DD66A23B-CB45-4AAA-818A-4081DA9C875B}" ProjectSection(SolutionItems) = preProject @@ -13,6 +13,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution nuget.config = nuget.config EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetSharp.Tests", "NetSharp.Tests\NetSharp.Tests.csproj", "{20FCC003-4342-49E3-9F66-640458C74B02}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetSharp.Benchmarks", "NetSharp.Benchmarks\NetSharp.Benchmarks.csproj", "{1C01A0C1-49C9-4B27-A4C8-7C66081982DC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -27,6 +31,14 @@ Global {5861E518-E712-4031-9AA1-0313736FF957}.Debug|Any CPU.Build.0 = Debug|Any CPU {5861E518-E712-4031-9AA1-0313736FF957}.Release|Any CPU.ActiveCfg = Release|Any CPU {5861E518-E712-4031-9AA1-0313736FF957}.Release|Any CPU.Build.0 = Release|Any CPU + {20FCC003-4342-49E3-9F66-640458C74B02}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {20FCC003-4342-49E3-9F66-640458C74B02}.Debug|Any CPU.Build.0 = Debug|Any CPU + {20FCC003-4342-49E3-9F66-640458C74B02}.Release|Any CPU.ActiveCfg = Release|Any CPU + {20FCC003-4342-49E3-9F66-640458C74B02}.Release|Any CPU.Build.0 = Release|Any CPU + {1C01A0C1-49C9-4B27-A4C8-7C66081982DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1C01A0C1-49C9-4B27-A4C8-7C66081982DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1C01A0C1-49C9-4B27-A4C8-7C66081982DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1C01A0C1-49C9-4B27-A4C8-7C66081982DC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NetSharp/NetSharp/AssemblyAttributes.cs b/NetSharp/NetSharp/AssemblyAttributes.cs @@ -1,5 +1,5 @@ using System.Resources; using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("NetSharpExamples", AllInternalsVisible = true)] +[assembly: InternalsVisibleTo("NetSharp.Benchmarks", AllInternalsVisible = true)] [assembly: NeutralResourcesLanguage("en")] \ No newline at end of file diff --git a/NetSharp/NetSharp/INetworkReader.cs b/NetSharp/NetSharp/INetworkReader.cs @@ -1,9 +0,0 @@ -namespace NetSharp -{ - public interface INetworkReader - { - public void Shutdown(); - - public void Start(ushort concurrentTasks); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/INetworkWriter.cs b/NetSharp/NetSharp/INetworkWriter.cs @@ -1,22 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace NetSharp -{ - public interface INetworkWriter - { - public int Read(ref EndPoint remoteEndPoint, Memory<byte> readBuffer, - SocketFlags flags = SocketFlags.None); - - public ValueTask<int> ReadAsync(EndPoint remoteEndPoint, Memory<byte> readBuffer, - SocketFlags flags = SocketFlags.None); - - public int Write(EndPoint remoteEndPoint, ReadOnlyMemory<byte> writeBuffer, - SocketFlags flags = SocketFlags.None); - - public ValueTask<int> WriteAsync(EndPoint remoteEndPoint, ReadOnlyMemory<byte> writeBuffer, - SocketFlags flags = SocketFlags.None); - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Interfaces/INetworkReader.cs b/NetSharp/NetSharp/Interfaces/INetworkReader.cs @@ -0,0 +1,9 @@ +namespace NetSharp.Interfaces +{ + public interface INetworkReader + { + public void Shutdown(); + + public void Start(ushort concurrentTasks); + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp/Interfaces/INetworkWriter.cs b/NetSharp/NetSharp/Interfaces/INetworkWriter.cs @@ -0,0 +1,22 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; + +namespace NetSharp.Interfaces +{ + public interface INetworkWriter + { + public int Read(ref EndPoint remoteEndPoint, Memory<byte> readBuffer, + SocketFlags flags = SocketFlags.None); + + public ValueTask<int> ReadAsync(EndPoint remoteEndPoint, Memory<byte> readBuffer, + SocketFlags flags = SocketFlags.None); + + public int Write(EndPoint remoteEndPoint, ReadOnlyMemory<byte> writeBuffer, + SocketFlags flags = SocketFlags.None); + + public ValueTask<int> WriteAsync(EndPoint remoteEndPoint, ReadOnlyMemory<byte> writeBuffer, + SocketFlags flags = SocketFlags.None); + } +} +\ No newline at end of file diff --git a/NetSharp/NetSharp/Raw/RawNetworkReaderBase.cs b/NetSharp/NetSharp/Raw/RawNetworkReaderBase.cs @@ -2,6 +2,8 @@ using System.Net.Sockets; using System.Threading; +using NetSharp.Interfaces; + namespace NetSharp.Raw { public abstract class RawNetworkReaderBase : RawNetworkConnectionBase, INetworkReader diff --git a/NetSharp/NetSharp/Raw/RawNetworkWriterBase.cs b/NetSharp/NetSharp/Raw/RawNetworkWriterBase.cs @@ -3,6 +3,8 @@ using System.Net; using System.Net.Sockets; using System.Threading.Tasks; +using NetSharp.Interfaces; + namespace NetSharp.Raw { public abstract class RawNetworkWriterBase : RawNetworkConnectionBase, INetworkWriter diff --git a/NetSharp/NetSharpExamples/BenchmarkHelper.cs b/NetSharp/NetSharpExamples/BenchmarkHelper.cs @@ -1,95 +0,0 @@ -using System; -using System.Diagnostics; - -namespace NetSharpExamples -{ - public sealed class BenchmarkHelper - { - private readonly Stopwatch stopwatch = new Stopwatch(); - private long lastTicksSnapshot = 0, lastMsSnapshot = 0; - private long minRttMs = int.MaxValue, maxRttMs = int.MinValue; - private long minRttTicks = int.MaxValue, maxRttTicks = int.MinValue; - - public BenchmarkHelper() - { - stopwatch.Reset(); - } - - public long RttMs => stopwatch.ElapsedMilliseconds; - - public long RttTicks => stopwatch.ElapsedTicks; - - public double CalcBandwidth(long sentPacketCount, long packetSize) - { - long millis = stopwatch.ElapsedMilliseconds; - double megabytes = sentPacketCount * packetSize / 1_000_000.0; - double bandwidth = megabytes / (millis / 1000.0); - - return bandwidth; - } - - public void PrintBandwidthStats(int clientId, long sentPacketCount, long packetSize) - { - long millis = stopwatch.ElapsedMilliseconds; - double megabytes = sentPacketCount * packetSize / 1_000_000.0; - double bandwidth = megabytes / (millis / 1000.0); - - lock (typeof(Console)) - { - Console.WriteLine($"[Client {clientId}] Sent {sentPacketCount} packets (of size {packetSize} bytes; {megabytes / 1000} gigabytes [one-way]) in {millis} milliseconds"); - Console.WriteLine($"[Client {clientId}] Approximate bandwidth: {bandwidth:F3} MBps"); - } - } - - public void PrintRttStats(int clientId) - { - lock (typeof(Console)) - { - Console.WriteLine($"[Client {clientId}] Min RTT: {minRttTicks} ticks, {minRttMs} ms"); - Console.WriteLine($"[Client {clientId}] Max RTT: {maxRttTicks} ticks, {maxRttMs} ms"); - } - } - - public void ResetStopwatch() - { - lastTicksSnapshot = 0; - lastMsSnapshot = 0; - - stopwatch.Reset(); - } - - public void SnapshotRttStats() - { - long elapsedTicksSnapshot = stopwatch.ElapsedTicks, elapsedMsSnapshot = stopwatch.ElapsedMilliseconds; - - minRttTicks = elapsedTicksSnapshot - lastTicksSnapshot < minRttTicks - ? elapsedTicksSnapshot - lastTicksSnapshot - : minRttTicks; - - minRttMs = elapsedMsSnapshot - lastMsSnapshot < minRttMs - ? elapsedMsSnapshot - lastMsSnapshot - : minRttMs; - - maxRttTicks = elapsedTicksSnapshot - lastTicksSnapshot > maxRttTicks - ? elapsedTicksSnapshot - lastTicksSnapshot - : maxRttTicks; - - maxRttMs = elapsedMsSnapshot - lastMsSnapshot > maxRttMs - ? elapsedMsSnapshot - lastMsSnapshot - : maxRttMs; - - lastTicksSnapshot = elapsedTicksSnapshot; - lastMsSnapshot = elapsedMsSnapshot; - } - - public void StartStopwatch() - { - stopwatch.Start(); - } - - public void StopStopwatch() - { - stopwatch.Stop(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkReaderBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkReaderBenchmark.cs @@ -1,118 +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.Datagram; - -namespace NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks -{ - internal class DatagramNetworkReaderBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000, ClientCount = 12; - private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; - private static readonly Encoding ServerEncoding = Program.DefaultEncoding; - private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - private double[] ClientBandwidths; - - /// <inheritdoc /> - public string Name { get; } = "Raw Datagram 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) - { - try - { - int id = (int) idObj; - - BenchmarkHelper benchmarkHelper = new BenchmarkHelper(); - - Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - clientSocket.Bind(ClientEndPoint); - - ServerReadyEvent.Wait(); - - byte[] sendBuffer = new byte[PacketSize]; - byte[] receiveBuffer = 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++) - { - byte[] packetBuffer = ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})"); - packetBuffer.CopyTo(sendBuffer, 0); - - benchmarkHelper.StartStopwatch(); - int sentBytes = clientSocket.SendTo(sendBuffer, remoteEndPoint); - - int receivedBytes = clientSocket.ReceiveFrom(receiveBuffer, ref remoteEndPoint); - benchmarkHelper.StopStopwatch(); - - benchmarkHelper.SnapshotRttStats(); - } - - benchmarkHelper.PrintBandwidthStats(id, PacketCount, PacketSize); - benchmarkHelper.PrintRttStats(id); - - ClientBandwidths[id] = benchmarkHelper.CalcBandwidth(PacketCount, PacketSize); - } - catch (Exception ex) - { - Console.WriteLine(ex); - } - - 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 defaultRemoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - - Socket rawSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - rawSocket.Bind(ServerEndPoint); - - using RawDatagramNetworkReader reader = new RawDatagramNetworkReader(ref rawSocket, RequestHandler, defaultRemoteEndPoint, PacketSize); - reader.Start(ClientCount); - - ServerReadyEvent.Set(); - - await Task.WhenAll(clientTasks); - - Console.WriteLine($"Total estimated bandwidth: {ClientBandwidths.Sum():F3}"); - - reader.Shutdown(); - - rawSocket.Close(); - rawSocket.Dispose(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterAsyncBenchmark.cs @@ -1,102 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using NetSharp.Raw.Datagram; - -namespace NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks -{ - internal class DatagramNetworkWriterAsyncBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000; - private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; - private static readonly Encoding ServerEncoding = Program.DefaultEncoding; - private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw Datagram Network Writer Benchmark (Asynchronous)"; - - private static Task ServerTask(CancellationToken cancellationToken) - { - using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - - server.Bind(ServerEndPoint); - ServerReadyEvent.Set(); - - byte[] transmissionBuffer = new byte[PacketSize]; - - 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() - { - 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.Dgram, ProtocolType.Udp); - rawSocket.Bind(ClientEndPoint); - - using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); - - using CancellationTokenSource serverCts = new CancellationTokenSource(); - Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); - - ServerReadyEvent.Wait(); - - 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.Close(); - rawSocket.Dispose(); - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Datagram Network Connection Benchmarks/DatagramNetworkWriterSyncBenchmark.cs @@ -1,98 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using NetSharp.Raw.Datagram; - -namespace NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks -{ - internal class DatagramNetworkWriterSyncBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000; - private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; - private static readonly Encoding ServerEncoding = Program.DefaultEncoding; - private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw Datagram Network Writer Benchmark (Synchronous)"; - - private static Task ServerTask(CancellationToken cancellationToken) - { - using Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); - - server.Bind(ServerEndPoint); - ServerReadyEvent.Set(); - - byte[] transmissionBuffer = new byte[PacketSize]; - - EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0); - - while (!cancellationToken.IsCancellationRequested) - { - int received = server.ReceiveFrom(transmissionBuffer, ref remoteEndPoint); - - int sent = server.SendTo(transmissionBuffer, remoteEndPoint); - } - - 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.Dgram, ProtocolType.Udp); - rawSocket.Bind(ClientEndPoint); - - using RawDatagramNetworkWriter writer = new RawDatagramNetworkWriter(ref rawSocket, defaultRemoteEndPoint, PacketSize); - - using CancellationTokenSource serverCts = new CancellationTokenSource(); - Task serverTask = Task.Factory.StartNew(state => ServerTask((CancellationToken) state), serverCts.Token, TaskCreationOptions.LongRunning); - - ServerReadyEvent.Wait(); - - 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(); - - rawSocket.Close(); - rawSocket.Dispose(); - - return Task.CompletedTask; - } - } -} -\ 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 @@ -1,142 +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.Packets; -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks -{ - internal class StreamNetworkReaderBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000, ClientCount = 12; - private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; - private static readonly Encoding ServerEncoding = Program.DefaultEncoding; - private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - private double[] ClientBandwidths; - - /// <inheritdoc /> - public string Name { get; } = "Raw 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); - - RawStreamPacketHeader streamPacketHeader = new RawStreamPacketHeader(PacketSize); - RawStreamPacket.Serialise(sendBuffer, in streamPacketHeader, packetBuffer); - - 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.Shutdown(); - - 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 @@ -1,129 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using NetSharp.Packets; -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks -{ - internal class StreamNetworkWriterAsyncBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000; - private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; - private static readonly Encoding ServerEncoding = Program.DefaultEncoding; - private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw 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(); - - RawStreamPacketHeader archetypalHeader = new RawStreamPacketHeader(PacketSize); - byte[] transmissionBuffer = new byte[RawStreamPacket.TotalPacketSize(in archetypalHeader)]; - - 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 @@ -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.Packets; -using NetSharp.Raw.Stream; - -namespace NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks -{ - internal class StreamNetworkWriterSyncBenchmark : INetSharpBenchmark - { - private const int PacketSize = 8192, PacketCount = 1_000_000; - private static readonly EndPoint ClientEndPoint = Program.DefaultClientEndPoint; - private static readonly Encoding ServerEncoding = Program.DefaultEncoding; - private static readonly EndPoint ServerEndPoint = Program.DefaultServerEndPoint; - private static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw 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(); - - // all the headers should have the same packet size, so will fit in the transmission buffer - RawStreamPacketHeader archetypalHeader = new RawStreamPacketHeader(PacketSize); - byte[] transmissionBuffer = new byte[RawStreamPacket.TotalPacketSize(in archetypalHeader)]; - - 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 < expectedBytes && receivedBytes > 0); - - if (receivedBytes == 0) - { - break; - } - - int sentBytes = 0; - do - { - sentBytes += clientSocket.Send(transmissionBuffer, sentBytes, expectedBytes - sentBytes, SocketFlags.None); - } while (sentBytes < expectedBytes && sentBytes > 0); - - 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/Examples/Datagram Network Connection Examples/DatagramNetworkReaderExample.cs b/NetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkReaderExample.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using NetSharp.Raw.Datagram; -namespace NetSharpExamples.Examples.Datagram_Network_Connection_Examples +namespace NetSharp.Examples.Examples.Datagram_Network_Connection_Examples { internal class DatagramNetworkReaderExample : INetSharpExample { diff --git a/NetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkWriterAsyncExample.cs b/NetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkWriterAsyncExample.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using NetSharp.Raw.Datagram; -namespace NetSharpExamples.Examples.Datagram_Network_Connection_Examples +namespace NetSharp.Examples.Examples.Datagram_Network_Connection_Examples { internal class DatagramNetworkWriterAsyncExample : INetSharpExample { diff --git a/NetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkWriterSyncExample.cs b/NetSharp/NetSharpExamples/Examples/Datagram Network Connection Examples/DatagramNetworkWriterSyncExample.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using NetSharp.Raw.Datagram; -namespace NetSharpExamples.Examples.Datagram_Network_Connection_Examples +namespace NetSharp.Examples.Examples.Datagram_Network_Connection_Examples { internal class DatagramNetworkWriterSyncExample : INetSharpExample { diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/RawStreamChatServer.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/RawStreamChatServer.cs @@ -7,7 +7,7 @@ using System.Threading.Tasks; using NetSharp.Raw.Stream; -namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples +namespace NetSharp.Examples.Examples.Stream_Network_Connection_Examples { internal class RawStreamChatServer : INetSharpExample { diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkReaderExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkReaderExample.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using NetSharp.Raw.Stream; -namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples +namespace NetSharp.Examples.Examples.Stream_Network_Connection_Examples { internal class StreamNetworkReaderExample : INetSharpExample { diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterAsyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterAsyncExample.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using NetSharp.Raw.Stream; -namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples +namespace NetSharp.Examples.Examples.Stream_Network_Connection_Examples { internal class StreamNetworkWriterAsyncExample : INetSharpExample { diff --git a/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterSyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/StreamNetworkWriterSyncExample.cs @@ -6,7 +6,7 @@ using System.Threading.Tasks; using NetSharp.Raw.Stream; -namespace NetSharpExamples.Examples.Stream_Network_Connection_Examples +namespace NetSharp.Examples.Examples.Stream_Network_Connection_Examples { internal class StreamNetworkWriterSyncExample : INetSharpExample { diff --git a/NetSharp/NetSharpExamples/INetSharpBenchmark.cs b/NetSharp/NetSharpExamples/INetSharpBenchmark.cs @@ -1,6 +0,0 @@ -namespace NetSharpExamples -{ - public interface INetSharpBenchmark : INetSharpExample - { - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharpExamples/INetSharpExample.cs b/NetSharp/NetSharpExamples/INetSharpExample.cs @@ -1,6 +1,6 @@ using System.Threading.Tasks; -namespace NetSharpExamples +namespace NetSharp.Examples { /// <summary> /// Defines an example program. diff --git a/NetSharp/NetSharpExamples/NetSharpExamples.csproj b/NetSharp/NetSharpExamples/NetSharp.Examples.csproj diff --git a/NetSharp/NetSharpExamples/NetSharpExamples.xml b/NetSharp/NetSharpExamples/NetSharpExamples.xml @@ -1,92 +1,56 @@ <?xml version="1.0"?> <doc> <assembly> - <name>NetSharpExamples</name> + <name>NetSharp.Examples</name> </assembly> <members> - <member name="P:NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks.DatagramNetworkReaderBenchmark.Name"> + <member name="P:NetSharp.Examples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkReaderExample.Name"> <inheritdoc /> </member> - <member name="M:NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks.DatagramNetworkReaderBenchmark.RunAsync"> + <member name="M:NetSharp.Examples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkReaderExample.RunAsync"> <inheritdoc /> </member> - <member name="P:NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks.DatagramNetworkWriterAsyncBenchmark.Name"> + <member name="P:NetSharp.Examples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterAsyncExample.Name"> <inheritdoc /> </member> - <member name="M:NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks.DatagramNetworkWriterAsyncBenchmark.RunAsync"> + <member name="M:NetSharp.Examples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterAsyncExample.RunAsync"> <inheritdoc /> </member> - <member name="P:NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks.DatagramNetworkWriterSyncBenchmark.Name"> + <member name="P:NetSharp.Examples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterSyncExample.Name"> <inheritdoc /> </member> - <member name="M:NetSharpExamples.Benchmarks.Datagram_Network_Connection_Benchmarks.DatagramNetworkWriterSyncBenchmark.RunAsync"> + <member name="M:NetSharp.Examples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterSyncExample.RunAsync"> <inheritdoc /> </member> - <member name="P:NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks.StreamNetworkReaderBenchmark.Name"> + <member name="P:NetSharp.Examples.Examples.Stream_Network_Connection_Examples.StreamNetworkReaderExample.Name"> <inheritdoc /> </member> - <member name="M:NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks.StreamNetworkReaderBenchmark.RunAsync"> + <member name="M:NetSharp.Examples.Examples.Stream_Network_Connection_Examples.StreamNetworkReaderExample.RunAsync"> <inheritdoc /> </member> - <member name="P:NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks.StreamNetworkWriterAsyncBenchmark.Name"> + <member name="P:NetSharp.Examples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterAsyncExample.Name"> <inheritdoc /> </member> - <member name="M:NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks.StreamNetworkWriterAsyncBenchmark.RunAsync"> + <member name="M:NetSharp.Examples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterAsyncExample.RunAsync"> <inheritdoc /> </member> - <member name="P:NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks.StreamNetworkWriterSyncBenchmark.Name"> + <member name="P:NetSharp.Examples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterSyncExample.Name"> <inheritdoc /> </member> - <member name="M:NetSharpExamples.Benchmarks.Stream_Network_Connection_Benchmarks.StreamNetworkWriterSyncBenchmark.RunAsync"> + <member name="M:NetSharp.Examples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterSyncExample.RunAsync"> <inheritdoc /> </member> - <member name="P:NetSharpExamples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkReaderExample.Name"> - <inheritdoc /> - </member> - <member name="M:NetSharpExamples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkReaderExample.RunAsync"> - <inheritdoc /> - </member> - <member name="P:NetSharpExamples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterAsyncExample.Name"> - <inheritdoc /> - </member> - <member name="M:NetSharpExamples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterAsyncExample.RunAsync"> - <inheritdoc /> - </member> - <member name="P:NetSharpExamples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterSyncExample.Name"> - <inheritdoc /> - </member> - <member name="M:NetSharpExamples.Examples.Datagram_Network_Connection_Examples.DatagramNetworkWriterSyncExample.RunAsync"> - <inheritdoc /> - </member> - <member name="P:NetSharpExamples.Examples.Stream_Network_Connection_Examples.StreamNetworkReaderExample.Name"> - <inheritdoc /> - </member> - <member name="M:NetSharpExamples.Examples.Stream_Network_Connection_Examples.StreamNetworkReaderExample.RunAsync"> - <inheritdoc /> - </member> - <member name="P:NetSharpExamples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterAsyncExample.Name"> - <inheritdoc /> - </member> - <member name="M:NetSharpExamples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterAsyncExample.RunAsync"> - <inheritdoc /> - </member> - <member name="P:NetSharpExamples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterSyncExample.Name"> - <inheritdoc /> - </member> - <member name="M:NetSharpExamples.Examples.Stream_Network_Connection_Examples.StreamNetworkWriterSyncExample.RunAsync"> - <inheritdoc /> - </member> - <member name="T:NetSharpExamples.INetSharpExample"> + <member name="T:NetSharp.Examples.INetSharpExample"> <summary> Defines an example program. </summary> </member> - <member name="P:NetSharpExamples.INetSharpExample.Name"> + <member name="P:NetSharp.Examples.INetSharpExample.Name"> <summary> The name of the example. </summary> </member> - <member name="M:NetSharpExamples.INetSharpExample.RunAsync"> + <member name="M:NetSharp.Examples.INetSharpExample.RunAsync"> <summary> Runs the example asynchronously. </summary> diff --git a/NetSharp/NetSharpExamples/Program.cs b/NetSharp/NetSharpExamples/Program.cs @@ -4,19 +4,16 @@ using System.Net; using System.Reflection; using System.Resources; using System.Text; -using System.Threading.Tasks; [assembly: NeutralResourcesLanguage("en")] -namespace NetSharpExamples +namespace NetSharp.Examples { internal class Program { - private static readonly List<INetSharpBenchmark> Benchmarks; + private const int DefaultExamplePort = 44230; private static readonly IPAddress DefaultExampleAddress = IPAddress.Loopback; - private static readonly int DefaultExamplePort = 44230; private static readonly List<INetSharpExample> Examples; - public static readonly EndPoint DefaultClientEndPoint = new IPEndPoint(DefaultExampleAddress, 0); public static readonly Encoding DefaultEncoding = Encoding.UTF8; public static readonly EndPoint DefaultServerEndPoint = new IPEndPoint(DefaultExampleAddress, DefaultExamplePort); @@ -25,11 +22,9 @@ namespace NetSharpExamples { Examples = new List<INetSharpExample>(); - Benchmarks = new List<INetSharpBenchmark>(); - foreach (Type type in Assembly.GetCallingAssembly().GetTypes()) { - if (!type.IsClass) + if (!type.IsClass && !type.IsValueType) { continue; } @@ -37,26 +32,15 @@ namespace NetSharpExamples Type[] interfaces = type.GetInterfaces(); object instance = Activator.CreateInstance(type); - switch (interfaces.Length) + if (type.GetInterface(nameof(INetSharpExample)) == typeof(INetSharpExample)) { - case 1 when type.GetInterface(nameof(INetSharpExample)) == typeof(INetSharpExample): - Examples.Add((INetSharpExample) instance); - break; - - case 2 when type.GetInterface(nameof(INetSharpBenchmark)) == typeof(INetSharpBenchmark): - Examples.Add((INetSharpExample) instance); - Benchmarks.Add((INetSharpBenchmark) instance); - break; + Examples.Add((INetSharpExample) instance); } } } - private static async Task Main() + private static void Main() { - Console.WriteLine("Hello World!"); - - await RunAllBenchmarks(); - while (true) { GC.Collect(); @@ -108,23 +92,5 @@ namespace NetSharpExamples Console.WriteLine(); } - - private static async Task RunAllBenchmarks() - { - Console.WriteLine("Run all benchmarks? (y/n)"); - string input = Console.ReadLine()?.ToLowerInvariant() ?? "n"; - - if (input == "y") - { - foreach (INetSharpBenchmark benchmark in Benchmarks) - { - Console.WriteLine($"Starting \'{benchmark.Name}\'..."); - await benchmark.RunAsync(); - Console.WriteLine($"Finished \'{benchmark.Name}\'!"); - - Console.WriteLine(); - } - } - } } } \ No newline at end of file