Internet of Things: How to create a simple Web server (part 1)

Today you can find many different boards in the market which have Ethernet socket or support Ethernet/Wi-Fi/3G shields. So, connection to Internet is a trivial task. I already mentioned several Azure services which you can use in order to send messages, store your data and analyze it. But I found that there are still some scenarios when customers don’t want to connect their devices to Internet. At the same time they still need access to data using phones, laptops etc. using local network without any special infrastructure. In this case there is a task, which requires to have a simple web server. Of course, you can try to create any type of server (not just Web) but in most cases it’s easy to use Web browser to get access to your data. It’s not very hard to implement several methods inside your IoT solution, which will prepare HTML output based on existing data. But what about Web server?

In order to do my research I decided to use Netduino and Galileo boards. In this post I will show code for Netduino in .NET and in the next post I am going to discuss more complex code for Galileo.

Because Netduino uses .NET Micro Framework, it’s easy to use already prepared classes, which will help to implement our code. The most important class there is HttpListener and you can find it in System.Http assembly which is not included to your references by default. This class allows to start listening HTTP request. In fact you can implement the following code inside your Main method:

  var httpListener = new HttpListener("http", 80);
 
 httpListener.Start();
 
 while(true)
 {
 var context = httpListener.GetContext();
 var buffer = Encoding.UTF8.GetBytes("<html><body>" + DateTime.Now + "</body></html>");
 context.Response.ContentLength64 = buffer.Length;
 context.Response.OutputStream.Write(buffer, 0, buffer.Length);
 context.Close();
 }
 

We just created an object of HttpListener type using http protocol and port 80 and initiated listening thanks to Start method there. In order to get request from users we should call GetContext method, which will be waiting for request. Once we have a request we can get information about Uri, parameters etc. and create a response. In our case we send back a simple Html document.

If you test this code, probably, it will work but there are two problems:

  • This code will work fine just for one user and if you have several requests, probably, your board will go down;

  • Usually you need to do something and not just listening to a request. If you  leave this implementation, you won’t have a place to put device’s logic there;

So, we need to update our code using threads. In order to avoid the first problem you can generate your HTML and send response in separate thread and there will be a separate thread for each request. At the same time you can start listening in separate thread as well. This approach will allow you to start listening and return to application’s logic. So, my code looks like this:

  new Thread(() =>
 {
 var httpListener = new HttpListener("http", 80);
 httpListener.Start();
 while (true)
 {
 var context = httpListener.GetContext();
 new Thread(() =>
 {
 var buffer = Encoding.UTF8.GetBytes("<html><body>" + 
 DateTime.Now + "</body></html>");
 context.Response.ContentLength64 = buffer.Length;
 context.Response.OutputStream.Write(buffer, 0, 
 buffer.Length);
 context.Close();
 }).Start();
 }
 }).Start();
 
 while(true)
 {
 //your logic
 }
 

If you have some time your can rewrite this code using delegates approach.

Finally, I want to share the code which shows how to get ip address of your board. It will help you to reach your board using Web browser:

  NetworkInterface ni;
 while (true)
 {
 ni = NetworkInterface.GetAllNetworkInterfaces()[0];
 
 if (ni.IPAddress != "0.0.0.0") break;
 Debug.Print("Waiting for an IP Address...");
 Thread.Sleep(1000);
 }
 Debug.Print(ni.IPAddress.ToString());
 

Next time we will use sockets in order to show how to build Web server on Galileo.