Netduino home hardware projects downloads community

Jump to content


The Netduino forums have been replaced by new forums at community.wildernesslabs.co. This site has been preserved for archival purposes only and the ability to make new accounts or posts has been turned off.
Photo

Simple multi-threaded web server


  • Please log in to reply
14 replies to this topic

#1 Jasper

Jasper

    New Member

  • Members
  • Pip
  • 5 posts
  • LocationNL

Posted 07 April 2011 - 08:25 PM

Hi all!

I just created a simple server class for the Netduino Plus I would like to share with you. I found myself programming sockets on many of my little projects, so I wanted a simple non-blocking web server that was generic enough to be re-used often.

So I made a little helper class for this purpose. Once the server is started, it takes a command and argument(s) from the requested url. For instance, if you would program your Netduino to be a thermostat, you would call
http://192.168.1.100/settemp/livingroom/21
to set the temperature in the living room to 21 degrees.

To define such a command, you provide the server class with a list of possible commands, together with the number of arguments needed. Whenever a valid command is received, the server fires the CommandReceived event, passing the command and arguments in the event arguments. When handling this event, you can pass a result string (or some html) back, which is then returned in the server response. The final result (though simple) is a web server that can handle all kinds of commands while all you have to do is to handle an event.

To use this class, instantiate it, add the list of commands and a handler for the CommandReceived event:
// Instantiate a new web server on port 80.
 WebServer server = new WebServer(80);

// Add a handler for commands that are received by the server.
server.CommandReceived += new WebServer.CommandReceivedHandler(server_CommandReceived);

// Add a command (this one has a single argument)
server.AllowedCommands.Add(new WebCommand("SetLed", 1));

// Start the server
server.Start();

I have attached the code, including a sample project. To run the sample:
  • Start debugging
  • Note the IP address of your Netduino in the output window
  • Call "http://[your-ip-address]/setled/on" from your web browser

Please let me know what you think of it.

Cheers,
Jasper

Attached Files



#2 Trey Aughenbaugh

Trey Aughenbaugh

    Advanced Member

  • Members
  • PipPipPip
  • 36 posts

Posted 08 April 2011 - 12:19 AM

Hi all!

I just created a simple server class for the Netduino Plus I would like to share with you. I found myself programming sockets on many of my little projects, so I wanted a simple non-blocking web server that was generic enough to be re-used often.

Please let me know what you think of it.

Cheers,
Jasper


Jasper, I like it.
I have not tested it, but I like the idea and from what I saw in the code, it looks good.
Thanks for sharing.

-Trey

#3 Michel Trahan

Michel Trahan

    Advanced Member

  • Members
  • PipPipPip
  • 155 posts

Posted 08 April 2011 - 01:19 AM

For instance, if you would program your Netduino to be a thermostat, you would call

http://192.168.1.100/settemp/livingroom/21
to set the temperature in the living room to 21 degrees.

Imagine a series of netduino mini (as thermostat) using XBee to communicate with a router, then imagine a base station (or multiple with touch screens) that can send command to all the other "sensors" through the router ... you could have all the thermostats in the house connected to a router and a series of control panels also connected to the router and have the computer send preprogrammed sequence to all ... you could even change settings from the office using the internet :)

Very good work Jasper ! Thanks !
Started with C in 1985, moved to Vb3 ... to vb6 and stopped. Now started with .Net and learning C# and VB.net and wishing VB.net was on MF !

#4 hari

hari

    Advanced Member

  • Members
  • PipPipPip
  • 131 posts

Posted 08 April 2011 - 03:25 AM

Jasper,
That's awesome!
Looks flexible and very easy to use. I'll have to try it. Thanks for sharing!
=Hari=

// Instantiate a new web server on port 80.
 WebServer server = new WebServer(80);

// Add a handler for commands that are received by the server.
server.CommandReceived += new WebServer.CommandReceivedHandler(server_CommandReceived);

// Add a command (this one has a single argument)
server.AllowedCommands.Add(new WebCommand("SetLed", 1));

// Start the server
server.Start();



#5 Bloemhof

Bloemhof

    New Member

  • Members
  • Pip
  • 5 posts

Posted 10 April 2011 - 05:20 PM

Hi Jasper, This works great!! Thanx. :D I have added to the code to control 3 x external LEDs - without any problem. Thank You. Albert

#6 Jasper

Jasper

    New Member

  • Members
  • Pip
  • 5 posts
  • LocationNL

Posted 10 April 2011 - 07:43 PM

Hi Jasper,

This works great!! Thanx. :D

I have added to the code to control 3 x external LEDs - without any problem.

Thank You.

Albert

Hi Albert,

Nice to hear, thanks. I guess next step will be adding password authentication, but I'd like to use SSL for that, which isn't available on Netduino yet...

Jasper

#7 Gui Ambros

Gui Ambros

    New Member

  • Members
  • Pip
  • 2 posts

Posted 10 April 2011 - 10:32 PM

Great stuff Jasper, thanks.

Just a quick bug report: the webserver will crash whenever it receives a request with less than 5 chars due to the string.Substring being used on unchecked data. For example, try telnet <netduino IP> and just hit enter..

Under controlled environments accessed only via a browser this won't be a problem, but if you expose your netduino to the outside world this could be an easy DoS.

I fixed this by changing the initial lines of InterpretRequest to:

            string commandData;

            // Remove GET + Space
            if (rawData.Length > 5)
                commandData = rawData.Substring(5, rawData.Length - 5);
            else
                return null;


#8 FelixEmman

FelixEmman

    Member

  • Members
  • PipPip
  • 25 posts

Posted 19 April 2011 - 02:26 AM

Jasper, I haven't tried your server yet -I don't have my N+ available now- but I see you use a single thread in your webserver. I've seen a few other webservers in the Netduino forums and while they are threaded, they can't handle many repeated requests. I really wish I has the time to attempt to code a webserver that spans new listener threads as more requests come in, but right now my focus is in other areas, so I'm just keeping an eye in the projects forum and webservers are always an interesting topic. The problem is that these small webservers can handle gracefully as long as you don't abuse them. Once you start submitting requests quickly, they choke and exception out with socket exceptions. So this is really intended to be just a suggestion or a future improvement idea, nothing else. Thanks for the contribution.

#9 Jasper

Jasper

    New Member

  • Members
  • Pip
  • 5 posts
  • LocationNL

Posted 19 April 2011 - 07:09 AM

Jasper,
I haven't tried your server yet -I don't have my N+ available now- but I see you use a single thread in your webserver.
I've seen a few other webservers in the Netduino forums and while they are threaded, they can't handle many repeated requests. I really wish I has the time to attempt to code a webserver that spans new listener threads as more requests come in, but right now my focus is in other areas, so I'm just keeping an eye in the projects forum and webservers are always an interesting topic.
The problem is that these small webservers can handle gracefully as long as you don't abuse them. Once you start submitting requests quickly, they choke and exception out with socket exceptions.
So this is really intended to be just a suggestion or a future improvement idea, nothing else.
Thanks for the contribution.

Hi FelixEmman,

Thanks for your comments. Your absolutely right. You don't really have to try out the code to see that this server wouldn't be able to handle massive request rates. Strategically though, I'm not sure if trying to make a Netduino webserver itself robust against big server loads (or even DoS-attacks?) is the way to go.

Instead of having this tiny processor facing the big bad internet, another option would be to have an 'ordinary' web server handle the inbound requests and do some load balancing towards the Netduino. This way, the Netduino isn't directly facing the internet, but a more robust (in terms of CPU and memory) web server is acting as a kind of proxy towards it. You could then more gracefully handle Netduino overloads. On the other hand, this option ruins the efficiency (and charm) of a tiny Netduino doing all the cool stuff.

Jasper

#10 Michael M

Michael M

    New Member

  • Members
  • Pip
  • 2 posts

Posted 29 April 2011 - 06:10 PM

Hey Jasper, this is great, thanks! I used this as a starting point, and restructured the code a bit. I used some object-oriented "best practices", like breaking the functionality into more classes (encapsulation). The WebServer class itself functions simply as a web server (i.e. it doesn't turn off LED's). That function, as well as request interpretation for that purpose, resides in a different class. This way you can write modular code that does what you want, and the WebServer class doesn't change much. I also made some changes that I probably didn't HAVE to make, but you know how it goes... I don't know if you want to use this, but as your project grows, you might find it easier. Good luck!

Attached Files



#11 Michel Trahan

Michel Trahan

    Advanced Member

  • Members
  • PipPipPip
  • 155 posts

Posted 30 April 2011 - 03:41 AM

I don't know if you want to use this, but as your project grows, you might find it easier. Good luck!

How do we discriminate the request received ? Where is the command string ? Where are the arguments ... needed ...

I find the other one easier to use ... you declare actions, you switch between the ones you defined ... How do you know which command to call ? Or I missed the whole point
Started with C in 1985, moved to Vb3 ... to vb6 and stopped. Now started with .Net and learning C# and VB.net and wishing VB.net was on MF !

#12 Michael M

Michael M

    New Member

  • Members
  • Pip
  • 2 posts

Posted 02 May 2011 - 02:12 AM

Well one thing about coding/coders - it's almost always easier for us to understand code that we wrote ourselves. That said, the commands are interpreted in the LedAction class. That class provides ALL behavior for responding to an LED request.

This callback allows you to quickly switch the "handling" of any http request.

 /// <summary>
 /// Handles the CommandReceived event.
 /// </summary>
 private static string server_CommandReceived(Request request)
 {
     //"hello world" implementation.
     //return (new HelloAction()).Action(request);

     //led control implementation
     return (new LedAction(Hardware.Led)).Action(request);
 }

Right now the only ones that work are HelloAction and LedAction, but others could easily be written in the same manner. I plan to write one which will return an html file from the sd card - like IIS or Apache.

I simplified the interpretation structure, because I don't really want to use the web server to light LED's - truthfully I'm not sure exactly WHAT I want to use it for yet. But this allows me to use it for just about anything, without rewriting the whole thing or copying code.

#13 Michel Trahan

Michel Trahan

    Advanced Member

  • Members
  • PipPipPip
  • 155 posts

Posted 02 May 2011 - 01:11 PM

I was asking about how do you discriminate which action to take in your main function on the netduino ... I know that the worker has the code to do the actions ... but how do we test which command was asked to the webserver ? If you only send one command, why do all that structure lol
Started with C in 1985, moved to Vb3 ... to vb6 and stopped. Now started with .Net and learning C# and VB.net and wishing VB.net was on MF !

#14 caEstrada

caEstrada

    Advanced Member

  • Members
  • PipPipPip
  • 84 posts

Posted 26 November 2012 - 11:39 PM

Thanks Jasper, very powerful, excellent design...regards,

#15 col

col

    New Member

  • Members
  • Pip
  • 7 posts

Posted 28 November 2012 - 10:38 PM

Thanks for share Jasper, a question i will send comand to set the pwm module ? like "setSpeed/30"




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

home    hardware    projects    downloads    community    where to buy    contact Copyright © 2016 Wilderness Labs Inc.  |  Legal   |   CC BY-SA
This webpage is licensed under a Creative Commons Attribution-ShareAlike License.