Non-Blocking Sockets Server with Tasks

In this example we have a Non-Blocking Sockets Server with Tasks using C#

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

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();
            new ReverseEcho().BeginAsync(c);
        }
    }
}

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

    private int _bytesRead;

    private TcpClient _client;

    private NetworkStream _stream;

    internal void BeginAsync(TcpClient c)
    {
        this._client = c;
        this._stream = c.GetStream();

        var task = Task.Factory.StartNew(this.Read);

        // Set up centralized error handling and cleanup:
        task.ContinueWith(
            ant => Console.WriteLine("Error: " + ant.Exception.Message), TaskContinuationOptions.OnlyOnFaulted);

        task.ContinueWith(
            ant =>
                {
                    if (this._stream != null)
                    {
                        this._stream.Close();
                    }

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

    private void Read()
    {
        // This will create a child task.
        Task< int > readChunk = Task< int >.Factory.FromAsync(
            this._stream.BeginRead, 
            this._stream.EndRead, 
            this._data, 
            this._bytesRead, 
            this._data.Length - this._bytesRead, 
            null, 
            TaskCreationOptions.AttachedToParent);

        // NB: Note that we need TaskContinuationOptions.AttachedToParent to ensure that 
        // the parent task's cleanup continuations don't fire until we're finishing
        // writing the response. The first printing of the book is missing this!
        readChunk.ContinueWith(
            this.Write, TaskContinuationOptions.NotOnFaulted | TaskContinuationOptions.AttachedToParent);
    }

    private void Write(Task< int > readChunk)
    {
        this._bytesRead += readChunk.Result;
        if (readChunk.Result > 0 && this._bytesRead < this._data.Length)
        {
            this.Read(); // More data to read!
            return;
        }

        Array.Reverse(this._data);
        Task.Factory.FromAsync(
            this._stream.BeginWrite, 
            this._stream.EndWrite, 
            this._data, 
            0, 
            this._data.Length, 
            null, 
            TaskCreationOptions.AttachedToParent);
    }
}

You can download all the Asynchronous Methods code examples here



Comments

No comments yet.

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.