Error message

Deprecated function: The each() function is deprecated. This message will be suppressed on further calls in menu_set_active_trail() (line 2344 of /home/paradi35/public_html/includes/menu.inc).

Simple C# Webserver

I wanted to set up a simple interface to serve information online without having to install a bunch of stuff and read through a bunch of documentation about configuration. I came up with a class and an interface in c# that should simplify/standardize some of my other projects.

The handler interface provides access to the request and response streams for each request

interface IRequestHandler
{   //same idea as a java servlet
    void handle(HttpListenerContext context);
}

Here is a simple single threaded server; requests block while processing. There are performance issues here if you intend to have your request handler doing any heavy lifting, but for doing something like processing a get request and sending/receiving some stuff on a serial port it gets the job done. This implementation can always be swapped out, what matters is giving my IRequestHandlers something to run from.

class Server
{
    protected HttpListener httpListener;
    protected IRequestHandler requestHandler;

    //path is something like http://localhost:8000/
    public Server(string path, IRequestHandler requestHandler)
    {
        this.requestHandler = requestHandler;

        httpListener = new HttpListener();
        httpListener.Prefixes.Add(path);
    }

    public void begin()
    {
        //does not return until server dies
        httpListener.Start();
        while (true)
        {
            HttpListenerContext context = httpListener.GetContext();
            requestHandler.handle(context);
        }
    }
}

To get an idea how to put the IRequestHandler to use I wrote a (hopefully) self-explanatory example. I havn't used this in any long running programs, so hopefully calling OutputStream.close() is all I have to do to properly kill the HttpListenerContext.

class SimpleHandler
{
    public void handle(HttpListenerContext context)
    {  
        byte[] bytes = Encoding.ASCII.GetBytes("hello world");
        context.Response.OutputStream.Write(bytes, 0, bytes.Length);
        context.Response.OutputStream.Close();
    }
}

This is a little more useful for serving up static content.

class StaticDataHandler : ServerFramework.IRequestHandler
{
    private byte[] data;
    public StaticDataHandler(string dataString)
    {
        data = Encoding.ASCII.GetBytes(dataString);
    }

    public StaticDataHandler(byte[] dataBytes)
    {
       data = dataBytes;
    }

    public void handle(HttpListenerContext context)
    {
        context.Response.OutputStream.Write(data, 0, data.Length);
        context.Response.OutputStream.Close();
    }
}

And here is how you would serve a couple static pages, the idea is to run one server per page.

class MyProgram
{
    static void Main(string[] args)
    {
        //make the handler objects
        IRequestHandler pageHandler0 = new StaticDataHandler("this is page 1");
        IRequestHandler pageHandler1 = new StaticDataHandler("this is page 2");

        //make the server objects
        ServerFramework.Server server0 = new ServerFramework.Server("http://localhost:8000/foo/", pageHandler0);
        ServerFramework.Server server1 = new ServerFramework.Server("http://localhost:8000/bar/", pageHandler1);

        //start the servers in threads; Server.begin blocks forever
        Thread threadedserver0 = new Thread(server0.begin);
        Thread threadedserver1 = new Thread(server1.begin);

        threadedserver0.Start();
        threadedserver1.Start();

        threadedserver0.Join();
        threadedserver1.Join();    

    }
}