Async/await HTTP server in C#

Since there has been a bit of interest for the code below I mocked together another version: Kernel.HttpServer.zip

Background

Ok, so there are already alternatives for web servers in C#. Some of them are very feature rich.

But I wanted to play around with TPL and async/await a bit so I put together a quick hack of a minimal HTTP-server.

The main focus here has been on the use of async await keyword in .Net 4.5 that allows for thread conservation while keeping the code clean. .Net will automatically manage thread pool. In theory this solution could hold 10 000 connections and still use only 10 threads.

Traditional a server like this would be implemented in one of two ways:

  • Synchronous: one dedicated thread per connected client.
  • Asynchronous: Required calls to Begin* and End* to form a sort of loop. Methods are re-executed for every receive or send operation and you have to split your code into several methods.

Task Parallel Library + await

With the introduction TPL the traditional thread model is encapsulated in a managed Task with a wide variety of functionality. This in itself is handy, works great with anonymous methods and is handled by .Net managed thread pool. In .Net 4.5 a new keyword “await” was introduced which magically allows us to pause methods while waiting for a synchronous operation. During this pause the thread returns to the thread pool to do other work, and upon resume a thread is assigned the task of continuing execution of the method. The magic is of course just an illusion and behind the scenes the compiler adds some code that resembles the yield implementation. It converts the method to a state machine allowing a thread to enter and exit a method at certain positions using goto-statements and labels.

An example of how await allows us to release the thread while waiting for write operation to complete, then flush the stream. This would traditionally either block a thread (synchronous) or require you to split code into two methods (asynchronous).

The code

As always you should consider security if you use this code. I have implemented a regex-check of the file, which is the only data we pass to the OS in any way. New version don’t contain any regex, its a gaping security hole! But a regex-check like that could probably easily be vulnerable to a prematurely null-terminated string for instance. (Don’t trust code.)

Listener.cs

Client.cs

Sample Program.cs

 

10 thoughts on “Async/await HTTP server in C#”

  1. It doesn’t working.

    _socket.SendAsync require SocketAsyncEventArgs and return bool
    await require void methode
    and so on..

    🙁
    Best Regards

    Reply
    • Hi

      Thanks for your feedback.
      Not really sure how I managed to copy-paste that wrong. It was supposed to be _networkStream, not _socket – so probably a last minute edit. Also fixed a race condition with async socket disposing related to that last error.

      Reply
  2. Great code, so far.

    headerBytes is missing. The GetContentType() method is too, but I can figure out how it works. I am stuck on headerBytes, though.

    Reply
    • The error was “await headerBytes” should be “var headerBytes”.
      I put the source into a new project and fixed it up, so latest version is downloadable from top of page. 🙂

      Reply
  3. Hi There,

    This is a great simple example of TPL being used in a real world scenario.

    At the minute i am trying to put together an asynchronous tcp server but to be honest there isn’t much info out there on building a reliable server using the new socketasynceventargs (At least none that are particularly easily read).
    This though by the looks of it implements it, though in a much more readable format much like the way a thread based implementation would except without a thread being created every time a client connects and allowing TPL to worry about the getting the tasks done. Would that be a fair assesment?

    What i was wondering is would this design allow for a large number of concurrently connected clients? I know you mentioned at the top of the page it could hold 10000 connections with 10 threads but have you tried this with concurrently sending clients? or would this literally handle requests in a similar fashion as a traditional asynchronous server.

    Also would this design make use of I/O completion ports

    Reply
    • Hi. I have not tested this with high concurrency, but I would like to “when I have time”®. 🙂

      Reply
  4. Hi,

    sorry for replying on a thead that’s almost two years old, but I really like this sample. Very clean and easy-to-follow way of dealing with something that could get pretty complicated if done “the old way”.

    One thing I’ve been wondering with these parallel setups though: How would you limit/control the number of concurrent connections the server allows?

    The only thing I can think of is keeping a list (preferably a ConcurrentCollection) of the processing task objects and using Thread.Sleep to wait until its count is below the limit before spawning a new task. Isn’t there a more elegant way of doing it?

    Thanks!

    Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from Tedds blog

Subscribe now to keep reading and get access to the full archive.

Continue reading