Non-Blocking Sockets Server with IAsyncResult

In this example we have a Non-Blocking Socket Server with IAsyncResult using C#

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;

    public class Server
    {
        public void Serve(IPAddress address, int port)
        {
            ThreadPool.SetMinThreads(50, 50);
            TcpListener listener = new TcpListener(address, port);
            listener.Start();
            while (true)
            {
                TcpClient c = listener.AcceptTcpClient();
                ThreadPool.QueueUserWorkItem(this.ReverseEcho, c);
            }
        }

        private void ReverseEcho(object client)
        {
            new ReverseEcho().Begin((TcpClient)client);
        }
    }

    internal class ReverseEcho
    {
        private readonly byte[] _data = new byte[5000];

        private int _bytesRead;

        private TcpClient _client;

        private NetworkStream _stream;

        internal void Begin(TcpClient c)
        {
            try
            {
                this._client = c;
                this._stream = c.GetStream();
                this.Read();
            }
            catch (Exception ex)
            {
                this.ProcessException(ex);
            }
        }

        private void Cleanup()
        {
            if (this._stream != null)
            {
                this._stream.Close();
            }

            if (this._client != null)
            {
                this._client.Close();
            }
        }

        private bool EndRead(IAsyncResult r)
        {
            // Returns false if there’s no more data
            int chunkSize = this._stream.EndRead(r);
            this._bytesRead += chunkSize;
            return chunkSize > 0 && this._bytesRead < this._data.Length; // More to read
        }

        private void ProcessException(Exception ex)
        {
            this.Cleanup();
            Console.WriteLine("Error: " + ex.Message);
        }

        private void Read()
        {
            // Read in a nonblocking fashion.
            while (true)
            {
                IAsyncResult r = this._stream.BeginRead(
                    this._data, this._bytesRead, this._data.Length - this._bytesRead, this.ReadCallback, null);

                // This will nearly always return in the next line:
                if (!r.CompletedSynchronously)
                {
                    return; // Handled by callback
                }

                if (!this.EndRead(r))
                {
                    break;
                }
            }

            this.Write();
        }

        private void ReadCallback(IAsyncResult r)
        {
            try
            {
                if (r.CompletedSynchronously)
                {
                    return;
                }

                if (this.EndRead(r))
                {
                    this.Read(); // More data to read!
                    return;
                }

                this.Write();
            }
            catch (Exception ex)
            {
                this.ProcessException(ex);
            }
        }

        private void Write()
        {
            Array.Reverse(this._data);
            this._stream.BeginWrite(this._data, 0, this._data.Length, this.WriteCallback, null);
        }

        private void WriteCallback(IAsyncResult r)
        {
            try
            {
                this._stream.EndWrite(r);
            }
            catch (Exception ex)
            {
                this.ProcessException(ex);
            }

            this.Cleanup();
        }
    }

You can download all the Asynchronous Methods code examples here



Comments

  1. pepepaco July 13th

    Comment Arrow

    nice example, I’d like to see and non-clocking client using same technique, regards.


Add Yours

  • Author Avatar

    YOU


Comment Arrow




About Author

Robert

Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the Universe trying to produce bigger and better idiots. So far, the Universe is winning hands down.