commit aae672ae5628ea0b34921d3b4363d5f09a16c853 parent 9d931dc2740ae1c0d269493e2ab27f1c6dec0edc Author: Mikolaj Lenczewski <mikolaj.lenczewski308@gmail.com> Date: Mon, 8 Jun 2020 18:41:17 +0100 Started slimming down RawStreamPacketReader and RawStreamPacketWriter to only function on variable-length packets Diffstat:
13 files changed, 218 insertions(+), 1129 deletions(-)
diff --git a/NetSharp/NetSharp/Raw/Stream/FixedPacketRawStreamNetworkReader.cs b/NetSharp/NetSharp/Raw/Stream/FixedPacketRawStreamNetworkReader.cs @@ -1,148 +0,0 @@ -using System.Net; -using System.Net.Sockets; -using System.Runtime.CompilerServices; - -namespace NetSharp.Raw.Stream -{ - public sealed class FixedPacketRawStreamNetworkReader : RawStreamNetworkReader - { - private readonly int messageSize; - - /// <inheritdoc /> - public FixedPacketRawStreamNetworkReader(ref Socket rawConnection, RawStreamRequestHandler? requestHandler, EndPoint defaultEndPoint, int messageSize, - int pooledBuffersPerBucket = 50, uint preallocatedStateObjects = 0) : base(ref rawConnection, requestHandler, defaultEndPoint, messageSize, - pooledBuffersPerBucket, preallocatedStateObjects) - { - this.messageSize = messageSize; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void ConfigureReceive(SocketAsyncEventArgs args, int dataSize) - { - byte[] receiveBuffer = BufferPool.Rent(dataSize); - args.SetBuffer(receiveBuffer, 0, dataSize); - - TransmissionToken token = new TransmissionToken(dataSize, 0); - args.UserToken = token; - } - - /// <inheritdoc /> - protected override void CompleteAccept(SocketAsyncEventArgs args) - { - switch (args.SocketError) - { - case SocketError.Success: - ConfigureReceive(args, messageSize); - 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; - - int expectedBytes = token.ExpectedBytes; - - switch (args.SocketError) - { - case SocketError.Success: - int receivedBytes = args.BytesTransferred, previousReceivedBytes = token.BytesTransferred, totalReceivedBytes = previousReceivedBytes + receivedBytes; - - if (totalReceivedBytes == expectedBytes) // transmission complete - { - EndPoint clientEndPoint = args.AcceptSocket.RemoteEndPoint; - - byte[] responseBuffer = BufferPool.Rent(messageSize); - - bool responseExists = RequestHandler(clientEndPoint, receiveBuffer, totalReceivedBytes, responseBuffer); - BufferPool.Return(receiveBuffer, true); - - if (responseExists) - { - args.SetBuffer(responseBuffer, 0, messageSize); - - TransmissionToken sendToken = new TransmissionToken(messageSize, 0); - args.UserToken = sendToken; - - StartSend(args); - return; - } - - BufferPool.Return(responseBuffer, true); - - ConfigureReceive(args, messageSize); - 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); - - ConfigureReceive(args, messageSize); - 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/NetSharp/Raw/Stream/FixedPacketRawStreamNetworkWriter.cs b/NetSharp/NetSharp/Raw/Stream/FixedPacketRawStreamNetworkWriter.cs @@ -1,286 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace NetSharp.Raw.Stream -{ - public sealed class FixedPacketRawStreamNetworkWriter : RawStreamNetworkWriter - { - private readonly int messageSize; - - /// <inheritdoc /> - public FixedPacketRawStreamNetworkWriter(ref Socket rawConnection, EndPoint defaultEndPoint, int messageSize, int pooledBuffersPerBucket = 50, - uint preallocatedStateObjects = 0) : base(ref rawConnection, defaultEndPoint, messageSize, pooledBuffersPerBucket, preallocatedStateObjects) - { - this.messageSize = messageSize; - } - - /// <inheritdoc /> - protected override void CompleteReceive(SocketAsyncEventArgs args) - { - AsyncStreamReadToken token = (AsyncStreamReadToken) args.UserToken; - - byte[] receiveBuffer = args.Buffer; - int expectedBytes = receiveBuffer.Length; - - switch (args.SocketError) - { - case SocketError.Success: - int receivedBytes = args.BytesTransferred, totalReceivedBytes = token.TotalReadBytes; - - if (totalReceivedBytes + receivedBytes == expectedBytes) // transmission complete - { - receiveBuffer.CopyTo(token.UserBuffer); - token.CompletionSource.SetResult(totalReceivedBytes + receivedBytes); - } - else if (0 < totalReceivedBytes + receivedBytes && totalReceivedBytes + receivedBytes < expectedBytes) // transmission not complete - { - // update user token to take account of newly read bytes - token = new AsyncStreamReadToken(in token, receivedBytes); - args.UserToken = token; - - args.SetBuffer(totalReceivedBytes, expectedBytes - receivedBytes); - - ContinueReceive(args); - return; - } - else if (receivedBytes == 0) // connection is dead - { - token.CompletionSource.SetException(new SocketException((int) SocketError.HostDown)); - } - break; - - case SocketError.OperationAborted: - token.CompletionSource.SetCanceled(); - break; - - default: - int errorCode = (int) args.SocketError; - token.CompletionSource.SetException(new SocketException(errorCode)); - break; - } - - BufferPool.Return(receiveBuffer, true); - ArgsPool.Return(args); - } - - /// <inheritdoc /> - protected override void CompleteSend(SocketAsyncEventArgs args) - { - AsyncStreamWriteToken token = (AsyncStreamWriteToken) args.UserToken; - - byte[] sendBuffer = args.Buffer; - int expectedBytes = sendBuffer.Length; - - switch (args.SocketError) - { - case SocketError.Success: - int sentBytes = args.BytesTransferred, totalSentBytes = token.TotalWrittenBytes; - - if (totalSentBytes + sentBytes == expectedBytes) // transmission complete - { - token.CompletionSource.SetResult(totalSentBytes + sentBytes); - } - else if (0 < totalSentBytes + sentBytes && totalSentBytes + sentBytes < expectedBytes) // transmission not complete - { - // update user token to take account of newly written bytes - token = new AsyncStreamWriteToken(in token, sentBytes); - args.UserToken = token; - - args.SetBuffer(totalSentBytes, expectedBytes - sentBytes); - - ContinueSend(args); - return; - } - else if (sentBytes == 0) // connection is dead - { - token.CompletionSource.SetException(new SocketException((int) SocketError.HostDown)); - } - break; - - case SocketError.OperationAborted: - token.CompletionSource.SetCanceled(); - break; - - default: - int errorCode = (int) args.SocketError; - token.CompletionSource.SetException(new SocketException(errorCode)); - break; - } - - BufferPool.Return(sendBuffer, true); - ArgsPool.Return(args); - } - - /// <inheritdoc /> - public override int Read(ref EndPoint remoteEndPoint, Memory<byte> readBuffer, SocketFlags flags = SocketFlags.None) - { - int totalBytes = readBuffer.Length; - if (totalBytes > messageSize) - { - throw new ArgumentException( - $"Cannot receive a message of size: {totalBytes} bytes; maximum message size: {messageSize} bytes", - nameof(readBuffer.Length) - ); - } - - int readBytes = 0; - - byte[] transmissionBuffer = BufferPool.Rent(totalBytes); - - do - { - readBytes += Connection.Receive(transmissionBuffer, readBytes, totalBytes - readBytes, flags); - } while (readBytes < totalBytes && readBytes != 0); - - transmissionBuffer.CopyTo(readBuffer); - BufferPool.Return(transmissionBuffer, true); - - return readBytes; - } - - /// <inheritdoc /> - public override ValueTask<int> ReadAsync(EndPoint remoteEndPoint, Memory<byte> readBuffer, SocketFlags flags = SocketFlags.None) - { - int totalBytes = readBuffer.Length; - if (totalBytes > messageSize) - { - throw new ArgumentException( - $"Cannot receive a message of size: {totalBytes} bytes; maximum message size: {messageSize} bytes", - nameof(readBuffer.Length) - ); - } - - TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); - SocketAsyncEventArgs args = ArgsPool.Rent(); - - byte[] transmissionBuffer = BufferPool.Rent(totalBytes); - - args.SetBuffer(transmissionBuffer, 0, messageSize); - - args.RemoteEndPoint = remoteEndPoint; - args.SocketFlags = flags; - - AsyncStreamReadToken token = new AsyncStreamReadToken(tcs, 0, in readBuffer); - args.UserToken = token; - - if (Connection.ReceiveAsync(args)) - { - return new ValueTask<int>(tcs.Task); - } - - CompleteReceive(args); - - return new ValueTask<int>(tcs.Task); - } - - /// <inheritdoc /> - public override int Write(EndPoint remoteEndPoint, ReadOnlyMemory<byte> writeBuffer, SocketFlags flags = SocketFlags.None) - { - int totalBytes = writeBuffer.Length; - if (totalBytes > messageSize) - { - throw new ArgumentException( - $"Cannot send a message of size: {totalBytes} bytes; maximum message size: {messageSize} bytes", - nameof(writeBuffer.Length) - ); - } - - int writtenBytes = 0; - - byte[] transmissionBuffer = BufferPool.Rent(totalBytes); - writeBuffer.CopyTo(transmissionBuffer); - - do - { - writtenBytes += Connection.Send(transmissionBuffer, writtenBytes, totalBytes - writtenBytes, flags); - } while (writtenBytes < totalBytes && writtenBytes != 0); - - BufferPool.Return(transmissionBuffer); - - return writtenBytes; - } - - /// <inheritdoc /> - public override ValueTask<int> WriteAsync(EndPoint remoteEndPoint, ReadOnlyMemory<byte> writeBuffer, SocketFlags flags = SocketFlags.None) - { - int totalBytes = writeBuffer.Length; - if (totalBytes > messageSize) - { - throw new ArgumentException( - $"Cannot send a message of size: {totalBytes} bytes; maximum message size: {messageSize} bytes", - nameof(writeBuffer.Length) - ); - } - - TaskCompletionSource<int> tcs = new TaskCompletionSource<int>(); - SocketAsyncEventArgs args = ArgsPool.Rent(); - - byte[] transmissionBuffer = BufferPool.Rent(totalBytes); - writeBuffer.CopyTo(transmissionBuffer); - - args.SetBuffer(transmissionBuffer, 0, messageSize); - - args.RemoteEndPoint = remoteEndPoint; - args.SocketFlags = flags; - - AsyncStreamWriteToken token = new AsyncStreamWriteToken(tcs, 0); - args.UserToken = token; - - if (Connection.SendAsync(args)) - { - return new ValueTask<int>(tcs.Task); - } - - CompleteSend(args); - - return new ValueTask<int>(tcs.Task); - } - - private readonly struct AsyncStreamReadToken - { - public readonly TaskCompletionSource<int> CompletionSource; - public readonly int TotalReadBytes; - public readonly Memory<byte> UserBuffer; - - public AsyncStreamReadToken(TaskCompletionSource<int> completionSource, int totalReadBytes, in Memory<byte> userBuffer) - { - CompletionSource = completionSource; - - TotalReadBytes = totalReadBytes; - - UserBuffer = userBuffer; - } - - public AsyncStreamReadToken(in AsyncStreamReadToken previousToken, int newlyReadBytes) - { - CompletionSource = previousToken.CompletionSource; - - TotalReadBytes = previousToken.TotalReadBytes + newlyReadBytes; - - UserBuffer = previousToken.UserBuffer; - } - } - - private readonly struct AsyncStreamWriteToken - { - public readonly TaskCompletionSource<int> CompletionSource; - public readonly int TotalWrittenBytes; - - public AsyncStreamWriteToken(TaskCompletionSource<int> completionSource, int totalWrittenBytes) - { - CompletionSource = completionSource; - - TotalWrittenBytes = totalWrittenBytes; - } - - public AsyncStreamWriteToken(in AsyncStreamWriteToken previousToken, int newlyWrittenBytes) - { - CompletionSource = previousToken.CompletionSource; - - TotalWrittenBytes = previousToken.TotalWrittenBytes + newlyWrittenBytes; - } - } - } -} -\ No newline at end of file diff --git a/NetSharp/NetSharp/Raw/Stream/RawStreamNetworkReader.cs b/NetSharp/NetSharp/Raw/Stream/RawStreamNetworkReader.cs @@ -1,19 +1,18 @@ using System; using System.Net; using System.Net.Sockets; -using System.Runtime.CompilerServices; namespace NetSharp.Raw.Stream { public delegate bool RawStreamRequestHandler(EndPoint remoteEndPoint, in ReadOnlyMemory<byte> requestBuffer, int receivedRequestBytes, in Memory<byte> responseBuffer); - public abstract class RawStreamNetworkReader : RawNetworkReaderBase + public sealed class RawStreamNetworkReader : RawNetworkReaderBase { - protected readonly RawStreamRequestHandler RequestHandler; + private readonly RawStreamRequestHandler RequestHandler; /// <inheritdoc /> - protected RawStreamNetworkReader(ref Socket rawConnection, RawStreamRequestHandler? requestHandler, EndPoint defaultEndPoint, int maxMessageSize, + public RawStreamNetworkReader(ref Socket rawConnection, RawStreamRequestHandler? requestHandler, EndPoint defaultEndPoint, int maxMessageSize, int pooledBuffersPerBucket = 50, uint preallocatedStateObjects = 0) : base(ref rawConnection, defaultEndPoint, maxMessageSize, pooledBuffersPerBucket, preallocatedStateObjects) { @@ -32,55 +31,157 @@ namespace NetSharp.Raw.Stream return requestBuffer.TryCopyTo(responseBuffer); } - private void HandleIoCompleted(object sender, SocketAsyncEventArgs args) + private void CloseClientConnection(SocketAsyncEventArgs args) { - switch (args.LastOperation) + byte[] rentedBuffer = args.Buffer; + BufferPool.Return(rentedBuffer, true); + + Socket clientSocket = args.AcceptSocket; + + clientSocket.Shutdown(SocketShutdown.Both); + clientSocket.Close(); + clientSocket.Dispose(); + + ArgsPool.Return(args); + } + + private void CompleteAccept(SocketAsyncEventArgs args) + { + switch (args.SocketError) { - case SocketAsyncOperation.Accept: - StartDefaultAccept(); - CompleteAccept(args); + case SocketError.Success: + ConfigureReceiveHeader(args); + StartReceive(args); break; - case SocketAsyncOperation.Send: - CompleteSend(args); + default: + ArgsPool.Return(args); break; + } + } - case SocketAsyncOperation.Receive: - CompleteReceive(args); + private void CompleteReceive(SocketAsyncEventArgs args) + { + void CompleteReceiveHeader(SocketAsyncEventArgs args) + { + Memory<byte> headerBuffer = args.Buffer; + + RawStreamPacketHeader header = RawStreamPacketHeader.Deserialise(in headerBuffer); + + // TODO configure the number of bytes of data to receive + ConfigureReceiveData(args, in header); + StartReceive(args); + } + + void CompleteReceiveData(SocketAsyncEventArgs args) + { + byte[] dataBuffer = args.Buffer; + + // TODO handle request packet + //bool haveResponsePacket = RequestHandler(args.AcceptSocket.RemoteEndPoint, ); + + ConfigureSendHeader(args); + StartSend(args); + } + + bool receivingHeader = args.Buffer.Length == RawStreamPacketHeader.TotalSize; + + switch (args.SocketError) + { + case SocketError.Success: + switch (receivingHeader) + { + case true: + CompleteReceiveHeader(args); + break; + + case false: + CompleteReceiveData(args); + break; + } + break; + + default: + CloseClientConnection(args); break; } } - /// <inheritdoc /> - protected sealed override bool CanReuseStateObject(ref SocketAsyncEventArgs instance) + private void CompleteSend(SocketAsyncEventArgs args) { - return true; + 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; + + switch (args.SocketError) + { + case SocketError.Success: + switch (sendingHeader) + { + case true: + CompleteSendHeader(args); + break; + + case false: + CompleteSendData(args); + break; + } + break; + + default: + CloseClientConnection(args); + break; + } } - protected void CloseClientConnection(SocketAsyncEventArgs args) + private void ConfigureReceiveData(SocketAsyncEventArgs args, in RawStreamPacketHeader receivedPacketHeader) { - args.BufferList = null; + byte[] pendingPacketDataBuffer = BufferPool.Rent(receivedPacketHeader.DataSize); - byte[] rentedBuffer = args.Buffer; - BufferPool.Return(rentedBuffer, true); + args.SetBuffer(pendingPacketDataBuffer, 0, pendingPacketDataBuffer.Length); + } - Socket clientSocket = args.AcceptSocket; + private void ConfigureReceiveHeader(SocketAsyncEventArgs args) + { + byte[] pendingPacketHeaderBuffer = BufferPool.Rent(RawStreamPacketHeader.TotalSize); - clientSocket.Shutdown(SocketShutdown.Both); - clientSocket.Close(); - clientSocket.Dispose(); + args.SetBuffer(pendingPacketHeaderBuffer, 0, pendingPacketHeaderBuffer.Length); + } - ArgsPool.Return(args); + 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); } - protected abstract void CompleteAccept(SocketAsyncEventArgs args); + private void ConfigureSendHeader(SocketAsyncEventArgs args, in RawStreamPacket pendingPacket) + { + byte[] pendingPacketHeaderBuffer = BufferPool.Rent(RawStreamPacketHeader.TotalSize); - protected abstract void CompleteReceive(SocketAsyncEventArgs args); + pendingPacket.Header.Serialise(pendingPacketHeaderBuffer); - protected abstract void CompleteSend(SocketAsyncEventArgs args); + args.SetBuffer(pendingPacketHeaderBuffer, 0, pendingPacketHeaderBuffer.Length); + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void ContinueReceive(SocketAsyncEventArgs args) + private void ContinueReceive(SocketAsyncEventArgs args) { if (ShutdownToken.IsCancellationRequested) { @@ -98,8 +199,7 @@ namespace NetSharp.Raw.Stream CompleteReceive(args); } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected void ContinueSend(SocketAsyncEventArgs args) + private void ContinueSend(SocketAsyncEventArgs args) { if (ShutdownToken.IsCancellationRequested) { @@ -117,29 +217,26 @@ namespace NetSharp.Raw.Stream CompleteSend(args); } - /// <inheritdoc /> - protected sealed override SocketAsyncEventArgs CreateStateObject() + private void HandleIoCompleted(object sender, SocketAsyncEventArgs args) { - SocketAsyncEventArgs args = new SocketAsyncEventArgs(); - args.Completed += HandleIoCompleted; - - return args; - } + switch (args.LastOperation) + { + case SocketAsyncOperation.Accept: + StartDefaultAccept(); + CompleteAccept(args); + break; - /// <inheritdoc /> - protected sealed override void DestroyStateObject(SocketAsyncEventArgs instance) - { - instance.Completed -= HandleIoCompleted; - instance.Dispose(); - } + case SocketAsyncOperation.Send: + CompleteSend(args); + break; - /// <inheritdoc /> - protected sealed override void ResetStateObject(ref SocketAsyncEventArgs instance) - { - instance.AcceptSocket = null; + case SocketAsyncOperation.Receive: + CompleteReceive(args); + break; + } } - protected void StartAccept(SocketAsyncEventArgs args) + private void StartAccept(SocketAsyncEventArgs args) { if (ShutdownToken.IsCancellationRequested) { @@ -155,7 +252,7 @@ namespace NetSharp.Raw.Stream CompleteAccept(args); } - protected void StartDefaultAccept() + private void StartDefaultAccept() { if (ShutdownToken.IsCancellationRequested) { @@ -166,7 +263,7 @@ namespace NetSharp.Raw.Stream StartAccept(args); } - protected void StartReceive(SocketAsyncEventArgs args) + private void StartReceive(SocketAsyncEventArgs args) { if (ShutdownToken.IsCancellationRequested) { @@ -184,7 +281,7 @@ namespace NetSharp.Raw.Stream CompleteReceive(args); } - protected void StartSend(SocketAsyncEventArgs args) + private void StartSend(SocketAsyncEventArgs args) { if (ShutdownToken.IsCancellationRequested) { @@ -203,7 +300,35 @@ namespace NetSharp.Raw.Stream } /// <inheritdoc /> - public sealed override void Start(ushort concurrentReadTasks) + protected override bool CanReuseStateObject(ref SocketAsyncEventArgs instance) + { + return true; + } + + /// <inheritdoc /> + protected override SocketAsyncEventArgs CreateStateObject() + { + SocketAsyncEventArgs args = new SocketAsyncEventArgs(); + args.Completed += HandleIoCompleted; + + return args; + } + + /// <inheritdoc /> + protected override void DestroyStateObject(SocketAsyncEventArgs instance) + { + instance.Completed -= HandleIoCompleted; + instance.Dispose(); + } + + /// <inheritdoc /> + protected override void ResetStateObject(ref SocketAsyncEventArgs instance) + { + instance.AcceptSocket = null; + } + + /// <inheritdoc /> + public override void Start(ushort concurrentReadTasks) { for (ushort i = 0; i < concurrentReadTasks; i++) { @@ -211,7 +336,7 @@ namespace NetSharp.Raw.Stream } } - protected readonly struct TransmissionToken + private readonly struct TransmissionToken { public readonly int BytesTransferred; public readonly int ExpectedBytes; diff --git a/NetSharp/NetSharp/Raw/Stream/RawStreamPacket.cs b/NetSharp/NetSharp/Raw/Stream/RawStreamPacket.cs @@ -7,63 +7,61 @@ namespace NetSharp.Raw.Stream public readonly struct RawStreamPacket { public readonly Memory<byte> Data; - public readonly Header PacketHeader; + public readonly RawStreamPacketHeader Header; - private RawStreamPacket(in Header header, in Memory<byte> data) + private RawStreamPacket(in RawStreamPacketHeader packetHeader, in Memory<byte> packetData) { - PacketHeader = header; + Header = packetHeader; - Data = data; + Data = packetData; } - public RawStreamPacket(in Memory<byte> data) + public RawStreamPacket(in Memory<byte> packetData) { - PacketHeader = new Header(data.Length); + Header = new RawStreamPacketHeader(packetData.Length); - Data = data; + Data = packetData; } public static RawStreamPacket Deserialise(in Memory<byte> buffer) { - Memory<byte> serialisedHeader = buffer.Slice(0, Header.TotalHeaderSize); - Header header = Header.Deserialise(in serialisedHeader); + Memory<byte> serialisedHeader = buffer.Slice(0, RawStreamPacketHeader.TotalSize); + RawStreamPacketHeader header = RawStreamPacketHeader.Deserialise(in serialisedHeader); - Memory<byte> serialisedData = buffer.Slice(Header.TotalHeaderSize); - - return new RawStreamPacket(in header, in serialisedData); + return new RawStreamPacket(in header, in buffer); } public void Serialise(in Memory<byte> buffer) { - PacketHeader.Serialise(buffer.Slice(0, Header.TotalHeaderSize)); + Header.Serialise(buffer.Slice(0, RawStreamPacketHeader.TotalSize)); - Data.CopyTo(buffer.Slice(Header.TotalHeaderSize, Data.Length)); + Buffer.CopyTo(buffer.Slice(RawStreamPacketHeader.TotalSize, Data.Length)); } + } - public readonly struct Header - { - public const int TotalHeaderSize = sizeof(int); + public readonly struct RawStreamPacketHeader + { + public const int TotalSize = sizeof(int); - public readonly int DataSize; + public readonly int DataSize; - internal Header(int dataSize) - { - DataSize = dataSize; - } + internal RawStreamPacketHeader(int dataSize) + { + DataSize = dataSize; + } - public static Header Deserialise(in Memory<byte> buffer) - { - Span<byte> serialisedDataSize = buffer.Slice(0, sizeof(int)).Span; - int dataSize = EndianAwareBitConverter.ToInt32(serialisedDataSize); + public static RawStreamPacketHeader Deserialise(in Memory<byte> buffer) + { + Span<byte> serialisedDataSize = buffer.Slice(0, sizeof(int)).Span; + int dataSize = EndianAwareBitConverter.ToInt32(serialisedDataSize); - return new Header(dataSize); - } + return new RawStreamPacketHeader(dataSize); + } - public void Serialise(in Memory<byte> buffer) - { - Span<byte> serialisedDataSize = EndianAwareBitConverter.GetBytes(DataSize); - serialisedDataSize.CopyTo(buffer.Slice(0, sizeof(int)).Span); - } + public void Serialise(in Memory<byte> buffer) + { + Span<byte> serialisedDataSize = EndianAwareBitConverter.GetBytes(DataSize); + serialisedDataSize.CopyTo(buffer.Slice(0, sizeof(int)).Span); } } } \ No newline at end of file diff --git a/NetSharp/NetSharp/Raw/Stream/VariablePacketRawStreamNetworkReader.cs b/NetSharp/NetSharp/Raw/Stream/VariablePacketRawStreamNetworkReader.cs @@ -1,10 +1,6 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Runtime.CompilerServices; - -namespace NetSharp.Raw.Stream +namespace NetSharp.Raw.Stream { + /* public sealed class VariablePacketRawStreamNetworkReader : RawStreamNetworkReader { /// <inheritdoc /> @@ -179,4 +175,5 @@ namespace NetSharp.Raw.Stream } } } + */ } \ No newline at end of file diff --git a/NetSharp/NetSharp/Raw/Stream/VariablePacketRawStreamNetworkWriter.cs b/NetSharp/NetSharp/Raw/Stream/VariablePacketRawStreamNetworkWriter.cs @@ -1,10 +1,6 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace NetSharp.Raw.Stream +namespace NetSharp.Raw.Stream { + /* public sealed class VariablePacketRawStreamNetworkWriter : RawStreamNetworkWriter { //TODO replace as soon as possible @@ -16,7 +12,6 @@ namespace NetSharp.Raw.Stream { } - /* [MethodImpl(MethodImplOptions.AggressiveInlining)] private void ConfigureReceiveData(SocketAsyncEventArgs args, in RawStreamPacket.Header header) { @@ -56,7 +51,6 @@ namespace NetSharp.Raw.Stream AsyncStreamWriteToken token = new AsyncStreamWriteToken(RawStreamPacket.Header.TotalHeaderSize, 0); args.UserToken = token; } - */ /// <inheritdoc /> protected override void CompleteReceive(SocketAsyncEventArgs args) @@ -361,4 +355,5 @@ namespace NetSharp.Raw.Stream } } } + */ } \ No newline at end of file diff --git a/NetSharp/NetSharp/Utils/SlimObjectPool.cs b/NetSharp/NetSharp/Utils/SlimObjectPool.cs @@ -9,7 +9,7 @@ namespace NetSharp.Utils /// <typeparam name="T"> /// The type of item stored in the pool. /// </typeparam> - public class SlimObjectPool<T> : IDisposable where T : class + public readonly struct SlimObjectPool<T> : IDisposable where T : class { private readonly CanRebufferObjectPredicate canObjectBeRebufferedPredicate; diff --git a/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/FixedPacketStreamNetworkReaderBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/FixedPacketStreamNetworkReaderBenchmark.cs @@ -1,140 +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 FixedPacketStreamNetworkReaderBenchmark : 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 Fixed 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]; - 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++) - { - ServerEncoding.GetBytes($"[Client {id}] Hello World! (Packet {i})").CopyTo(sendBuffer, 0); - - 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 FixedPacketRawStreamNetworkReader(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/FixedPacketStreamNetworkWriterAsyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/FixedPacketStreamNetworkWriterAsyncBenchmark.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 FixedPacketStreamNetworkWriterAsyncBenchmark : 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 = Encoding.UTF8; - public static readonly EndPoint ServerEndPoint = new IPEndPoint(IPAddress.Loopback, 12374); - - public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw Fixed 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 FixedPacketRawStreamNetworkWriter(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/FixedPacketStreamNetworkWriterSyncBenchmark.cs b/NetSharp/NetSharpExamples/Benchmarks/Stream Network Connection Benchmarks/FixedPacketStreamNetworkWriterSyncBenchmark.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 FixedPacketStreamNetworkWriterSyncBenchmark : 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 = FixedPacketStreamNetworkReaderBenchmark.ServerEncoding; - public static readonly EndPoint ServerEndPoint = FixedPacketStreamNetworkReaderBenchmark.ServerEndPoint; - - public static readonly ManualResetEventSlim ServerReadyEvent = new ManualResetEventSlim(); - - /// <inheritdoc /> - public string Name { get; } = "Raw Fixed 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 FixedPacketRawStreamNetworkWriter(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/FixedPacketStreamNetworkReaderExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/FixedPacketStreamNetworkReaderExample.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 FixedPacketStreamNetworkReaderExample : 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 Fixed 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 FixedPacketRawStreamNetworkReader(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/FixedPacketStreamNetworkWriterAsyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/FixedPacketStreamNetworkWriterAsyncExample.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 FixedPacketStreamNetworkWriterAsyncExample : INetSharpExample - { - private const int PacketSize = 8192; - - public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - - public static readonly Encoding ServerEncoding = FixedPacketStreamNetworkReaderExample.ServerEncoding; - public static readonly EndPoint ServerEndPoint = FixedPacketStreamNetworkReaderExample.ServerEndPoint; - - /// <inheritdoc /> - public string Name { get; } = "Raw Fixed 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 FixedPacketRawStreamNetworkWriter(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/FixedPacketStreamNetworkWriterSyncExample.cs b/NetSharp/NetSharpExamples/Examples/Stream Network Connection Examples/FixedPacketStreamNetworkWriterSyncExample.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 FixedPacketStreamNetworkWriterSyncExample : INetSharpExample - { - private const int PacketSize = 8192; - - public static readonly EndPoint ClientEndPoint = new IPEndPoint(IPAddress.Loopback, 0); - - public static readonly Encoding ServerEncoding = FixedPacketStreamNetworkReaderExample.ServerEncoding; - public static readonly EndPoint ServerEndPoint = FixedPacketStreamNetworkReaderExample.ServerEndPoint; - - /// <inheritdoc /> - public string Name { get; } = "Raw Fixed 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 FixedPacketRawStreamNetworkWriter(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