I am creating a server client app where after the connection is done, the server and client will send packages back and forward. The Stream can be a NetworkStream or SslStream.

I have created a Async ReadContinuously method and it seems to work, but I do not trust my own knowledge about Async yet. Can you guys tell me I am on the right track or not?

**Client:**

```
        private async void ListenToServer()
        {
            bool exitbyerror = false;

            //
            Queue<TestServerDataPacket> queue = new Queue<TestServerDataPacket>();

            try
            {
                await Task.Run(() =>
                {
                    // After this a Queue Reader must be created
                    _packetReader.ReadContinuously(_netStream, _connection.ReceiveBufferSize, queue);

                    // For Testing
                    while (_connection?.Connected == true)
                    {
                        //
                        Console.WriteLine("Client: ({0}) Packets in queue.", queue.Count);

                        // For Testing 
                        Thread.Sleep(2000);
                    }
                });
            }
            catch
            {
                exitbyerror = true;
            }

            //
            if (exitbyerror)
            {
                //
            }
        }

```

**PacketReader:**

```
        private bool _readContinuously;

        public void ReadContinuously(Stream s, int bufferSize, Queue<TestServerDataPacket> packetQueue)
        {
            try
            {
                if (s == null)
                {
                    throw new ArgumentNullException("Stream can not be null!");
                }
                if (packetQueue == null)
                {
                    throw new ArgumentNullException("Queue<TestServerDataPacket> can not be null!");
                }

                //
                _readContinuously = true;

                //
                DoReadContinuously(s, bufferSize, packetQueue);
            }
            catch
            {
                throw;
            }
        }
        private async void DoReadContinuously(Stream s, int bufferSize, Queue<TestServerDataPacket> packetQueue)
        {
            //
            byte[] buffer = new byte[bufferSize];

            //
            TestServerDataPacket packet;

            try
            {
                // Read Packet Length = 4 bytes
                int bytesReceived = 0;
                while (bytesReceived < 4)
                {
                    //
                    int byteread = await s.ReadAsync(buffer, bytesReceived, 4 - bytesReceived);

                    //
                    if (byteread == 0)
                    {
                        // 0 bytes read = end of stream / disconnected
                        throw new Exception("Connection Closed!");
                    }

                    //
                    bytesReceived += byteread;
                }
                bytesReceived = 0;

                // Get Packet Size
                int packetSize = BitConverter.ToInt32(buffer, 0);

                // Create Packet Byte Array
                byte[] packetbytes;

                // Read Data
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    // Read Data
                    while (bytesReceived < packetSize)
                    {
                        // Adjust Buffer size to catch only the packet and nothing else
                        if (buffer.Length > (packetSize - bytesReceived))
                        {
                            buffer = new byte[(packetSize - bytesReceived)];
                        }

                        //
                        int count;
                        if ((count = await s.ReadAsync(buffer, 0, buffer.Length)) > 0)
                        {
                            // Save Data
                            memoryStream.Write(buffer, 0, buffer.Length);

                            // Count
                            bytesReceived += count;
                        }
                    }

                    // Get Packet Bytes Array
                    packetbytes = memoryStream.GetBuffer();
                }

                // Create Packet
                DeserializeData(packetbytes, out packet);
            }
            catch
            {
                throw;
            }

            //
            if (packet != null)
            {
                packetQueue.Enqueue(packet);
            }

            //
            if (_readContinuously)
            {
                DoReadContinuously(s, bufferSize, packetQueue);
            }
        }

```

**Working test server:**

```
namespace TestServer
{
   public class Program
    {
        static void Main(string[] args)
        {
            TestServer server = new TestServer();

            TestClient client = new TestClient();

            Console.ReadLine();
        }
    }

    public class TestServer
    {
        private readonly TcpListener _listener;

        public TestServer()
        {
            IPEndPoint localEndPoint = new IPEndPoint(IPAddress.Any, 45654);

            _listener = new TcpListener(localEndPoint);
            _listener.Start(100);

            AcceptConnections();
        }
        private async void AcceptConnections()
        {
            await Task.Run(async () =>
            {
                try
                {
                    Socket s = await _listener.AcceptSocketAsync();
                    if (s != null)
                    {
                        Console.WriteLine("Server: Client Connected");
                        TestServerConnection c = new TestServerConnection(s);
                    }
                }
                catch
                {
                    //
                }
            });
        }
    }

    public class TestServerConnection
    {
        private readonly Socket _connection;
        private readonly TestPacketSender _packetSender;

        public TestServerConnection(Socket s)
        {
            _connection = s;

            _packetSender = new TestPacketSender(new NetworkStream(s, FileAccess.ReadWrite));

            Task.Factory.StartNew(ListenToClient);
        }
        private async Task ListenToClient()
        {
            bool exitbyerror = false;

            try
            {
                await Task.Run(() =>
                {
                    while (_connection?.Connected == true)
                    {
                        Thread.Sleep(10000);

                        Console.WriteLine("Server: Sending Hi");
                        _packetSender.Send(new TestServerDataPacket(2000)); // Int 2000 is Hi
                    }
                });
            }
            catch
            {
                exitbyerror = true;
            }

            //
            if (exitbyerror)
            {
                //
            }
        }
    }

    public class TestClient
    {
        private readonly Socket _connection;
        private NetworkStream _netStream;
        private TestPacketReader _packetReader;

        public TestClient()
        {
            _packetReader = new TestPacketReader();

            IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 45654);

            // Create a TCP/IP socket.  
            _connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
            {
                ReceiveBufferSize = (8 * 1024),
                SendBufferSize = (8 * 1024),
                NoDelay = true
            };

            // Connect to the remote endpoint.  
            _connection.Connect(remoteEndPoint);
            _netStream = new NetworkStream(_connection, FileAccess.ReadWrite);

            Console.WriteLine("Client: Connected to server.");

            Task.Factory.StartNew(ListenToServer);
        }
        private async void ListenToServer()
        {
            bool exitbyerror = false;

            //
            Queue<TestServerDataPacket> queue = new Queue<TestServerDataPacket>();

            try
            {
                await Task.Run(() =>
                {
                    // After this a Queue Reader must be created
                    _packetReader.ReadContinuously(_netStream, _connection.ReceiveBufferSize, queue);

                    // For Testing
                    while (_connection?.Connected == true)
                    {
                        //
                        Console.WriteLine("Client: ({0}) Packets in queue.", queue.Count);

                        // For Testing 
                        Thread.Sleep(2000);
                    }
                });
            }
            catch
            {
                exitbyerror = true;
            }

            //
            if (exitbyerror)
            {
                //
            }
        }
    }

    public class TestPacketSender
    {
        //
        private readonly Stream _stream;
        private readonly object _writingToStream = new object();

        //
        public TestPacketSender(Stream stream)
        {
            _stream = stream;
        }

        //
        public bool Send(TestServerDataPacket packet)
        {
            if (_stream == null)
            {
                throw new ArgumentNullException("Stream can not be null");
            }
            if (packet == null)
            {
                throw new ArgumentNullException("TestServerDataPacket can not be null!");
            }

            //
            lock (_writingToStream)
            {
                return SendToStream(_stream, packet);
            }
        }
        private bool SendToStream(Stream s, TestServerDataPacket packet)
        {
            try
            {
                // Byte Array containing Packet Size and Packet
                byte[] buffer;

                // Fill buffer (Packet Size + Packet Content)
                SerializeData(packet, out buffer);

                // Write Packet to the Stream
                s.Write(buffer, 0, buffer.Length);
                s.Flush();

                //
                return true;
            }
            catch
            {
                //
                return false;
            }
        }

        //
        private void SerializeData(TestServerDataPacket packet, out byte[] buffer)
        {
            if (packet == null)
            {
                buffer = new byte[0];
                return;
            }

            byte[] packetbytes;

            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream ms = new MemoryStream())
            {
                //
                formatter.Serialize(ms, packet);

                //
                packetbytes = ms.ToArray();
            }

            //
            buffer = CreatePacket(packetbytes);
        }
        private byte[] CreatePacket(byte[] packetbytes)
        {
            // Get the packet length
            byte[] lengthPrefix = BitConverter.GetBytes(packetbytes.Length);

            // 
            byte[] totalpacket = new byte[lengthPrefix.Length + packetbytes.Length];

            // Combine the packet length and the packet data
            lengthPrefix.CopyTo(totalpacket, 0);
            packetbytes.CopyTo(totalpacket, lengthPrefix.Length);

            //
            return totalpacket;
        }
    }
    public class TestPacketReader
    {
        private bool _readContinuously;

        public void ReadContinuously(Stream s, int bufferSize, Queue<TestServerDataPacket> packetQueue)
        {
            try
            {
                if (s == null)
                {
                    throw new ArgumentNullException("Stream can not be null!");
                }
                if (packetQueue == null)
                {
                    throw new ArgumentNullException("Queue<TestServerDataPacket> can not be null!");
                }

                //
                _readContinuously = true;

                //
                DoReadContinuously(s, bufferSize, packetQueue);
            }
            catch
            {
                throw;
            }
        }
        private async void DoReadContinuously(Stream s, int bufferSize, Queue<TestServerDataPacket> packetQueue)
        {
            //
            byte[] buffer = new byte[bufferSize];

            //
            TestServerDataPacket packet;

            try
            {
                // Read Packet Length = 4 bytes
                int bytesReceived = 0;
                while (bytesReceived < 4)
                {
                    //
                    int byteread = await s.ReadAsync(buffer, bytesReceived, 4 - bytesReceived);

                    //
                    if (byteread == 0)
                    {
                        // 0 bytes read = end of stream / disconnected
                        throw new Exception("Connection Closed!");
                    }

                    //
                    bytesReceived += byteread;
                }
                bytesReceived = 0;

                // Get Packet Size
                int packetSize = BitConverter.ToInt32(buffer, 0);

                // Create Packet Byte Array
                byte[] packetbytes;

                // Read Data
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    // Read Data
                    while (bytesReceived < packetSize)
                    {
                        // Adjust Buffer size to catch only the packet and nothing else
                        if (buffer.Length > (packetSize - bytesReceived))
                        {
                            buffer = new byte[(packetSize - bytesReceived)];
                        }

                        //
                        int count;
                        if ((count = await s.ReadAsync(buffer, 0, buffer.Length)) > 0)
                        {
                            // Save Data
                            memoryStream.Write(buffer, 0, buffer.Length);

                            // Count
                            bytesReceived += count;
                        }
                    }

                    // Get Packet Bytes Array
                    packetbytes = memoryStream.GetBuffer();
                }

                // Create Packet
                DeserializeData(packetbytes, out packet);
            }
            catch
            {
                throw;
            }

            //
            if (packet != null)
            {
                packetQueue.Enqueue(packet);
            }

            //
            if (_readContinuously)
            {
                DoReadContinuously(s, bufferSize, packetQueue);
            }
        }

        private void DeserializeData(byte[] data, out TestServerDataPacket packet)
        {
            BinaryFormatter formatter = new BinaryFormatter();
            using (MemoryStream stream = new MemoryStream())
            {
                //
                stream.Write(data, 0, data.Length);
                stream.Seek(0, SeekOrigin.Begin);

                //
                packet = (TestServerDataPacket)formatter.Deserialize(stream);
            }
        }
    }

    [Serializable]
    public class TestServerDataPacket
    {
        // Unique Id
        public readonly Guid Id;

        // Type
        public readonly TestServerPacketType Type;

        // Sugnal/Message
        public readonly int Signal = 0;

        //
        public TestServerDataPacket(int signal)
        {
            Id = Guid.NewGuid();

            Signal = signal;
            Type = TestServerPacketType.Signal;
        }
    }

    public enum TestServerPacketType
    {
        Signal
    }
}

```