Netduino home hardware projects downloads community

Jump to content


Photo

Updated web server


  • Please log in to reply
41 replies to this topic

#1 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 26 October 2010 - 06:31 PM

An updated simple web server for the Netduino Plus. Obviously based on the SocketServer .NET framework example and code posted here by oz-solutions and hari. Some slight tweaks to headers should help prevent lost requests when using IE9 beta. Has a Request object to help with parsing the incoming request. Threaded so your code can get on with whatever it's doing and still respond to a http request. [30/11/2010 - project updated]

Attached Files


  • HCB likes this

#2 hari

hari

    Advanced Member

  • Members
  • PipPipPip
  • 131 posts

Posted 26 October 2010 - 07:29 PM

This is awesome!
Bug fixes and new features magically appears without me doing anything! I gotta post more crappy code. Posted Image

Thanks Fred!
=Hari=

EDIT: Just looked at your code. Very nice! Clean and straightforward. Great job!

#3 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 6860 posts
  • LocationNew York, NY

Posted 26 October 2010 - 07:49 PM

Thanks for the contribution, Fred. It's funny how the little things are what make the big difference sometimes.

#4 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 304 posts
  • LocationIndiana, USA

Posted 28 October 2010 - 04:18 AM

I just ran this web server and it works nicely. But, I see that the web page markup is generated in the code and sent out as the response. So, I added a default.htm file to the project and set the build type as "Content". With regular C# apps, I expect this to deploy the Content file along-side the executables, but how do I access the text content from a content file? I tried enumerating over the files, but I get nothing. I also did this:
if (System.IO.File.Exists("default.htm")) Debug.Print("File Found");
But, Nothing, I actually can't see any folders or files. Is this just not possible on .NET Micro? I would rather not use the MicroSD for a few tiny htm files. Not to mention, I can't think of any simple deployment methods that don't involve shuffling the MicroSD card everytime I change the htm files...

My Plan B is to use an embedded resource, but I am having other problems there... The UTF-8 Encoding is crapping out on a symbol in the html file (I think). Still investigating that though.

-Valkyrie-MT

#5 Chris Walker

Chris Walker

    Secret Labs Staff

  • Moderators
  • 6860 posts
  • LocationNew York, NY

Posted 28 October 2010 - 04:23 AM

Valkyrie-MT, You could embed resources in your app--or you could put files on the SD card. Or you could create an "upload" mechanism in your webserver that would write to the MicroSD card. A few options... There is no "file system" on the microcontroller itself--just on the SD card. If you want to deploy files (and very small ones at that--since you have 128KB or so of flash space total), you'll want to use resources. Chris

#6 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 28 October 2010 - 08:54 AM

Valkyrie-MT, When I was posting this I was wondering whether it should be called a web server, but as I was following on from hari I stuck with it. You'll notice the neither of the classes (Listener and Request) are called web server because all it really does is listen on port 80 and send back a response. I wrote only what I needed for my project. Mine's a home automation project that can switch my garage light on and open the door - much like the original "/led/1" example. It's going to take a command over http (from an Android phone client) and then return the current status as XML> It needs to do this whilst also allowing some switches (and later an RFID reader) to work too. This is the sort of scope where I think the Netduino Plus is perfect. Serving files is all good, but you'll have to decide how best to do that yourself. Some good tips from Chris as you'd expect. Personally I think that anything more that some small html files to one or two clients and you could be looking at the wrong tool for the job. However, the resourcefulness of the people on here could well prove me wrong!

#7 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 28 October 2010 - 09:05 AM

Some other point I should probably add to this, prompted by bill.french's post: The "web server" part runs as a single thread and can cope with a single queue of requests one at a time. I specifically said "threaded" rather than "multi-threaded" as the app above runs two threads only. One thread proves it can still blink a LED, or in my case open my garage door. A second thread responds to http requests. I've tested it with two browser switching between them and hitting F5 a lot. That's probably about its limit. Don't expect it to go off doing a task that takes 10s in the RequestReveived event and be responding to further requests during that time. It wont. Sure, this could be done, but if you need this you'll have to jump into the wonderful world of multi-threaded programming yourself.

#8 Valkyrie-MT

Valkyrie-MT

    Advanced Member

  • Members
  • PipPipPip
  • 304 posts
  • LocationIndiana, USA

Posted 29 October 2010 - 12:51 AM

Fred, I completely agree with you and I could easily write what I want by generating html from code, but I think it's easier to maintain as html files. Also, I would like to see the community produce a single project for new users to download that will run and show a simple page of buttons for controlling and reading the Digital and Analog I/Os. I think having easily editable html files is much more easy to grasp and customize. I would also like to see it acquire an address by DHCP and use Netbios to expose itself on the local network with the name "netduino". This would be a great starter app for new users. The end result would be that a new user could download and run the project, then go to http://netduino and see a page of buttons to control the Netduino. I would love to see this finished in time for the official NetduinoPlus launch in late November too. The only piece that may not be ready in time is the Netbios, although I see there is some work being done there... -Valkyrie-MT

#9 Corey Kosak

Corey Kosak

    Advanced Member

  • Members
  • PipPipPip
  • 276 posts
  • LocationHoboken, NJ

Posted 09 November 2010 - 05:51 AM

There's kind of a funky bug with the "using" statement in Listener.cs that results in clientSockets not being disposed as quickly as they could be.

The culprit is here:

                using (clientSocket)
                {
                    Debug.Print("Accepting...");
                    clientSocket = listeningSocket.Accept();  // Accept is a blocking call

The "using" statement operates on the value of the clientSocket variable from the previous iteration of the loop, which leads to an off-by-one problem. This little program illustrates:

using System;
using Microsoft.SPOT;

namespace NetduinoApplication1 {
  public class Program {
    public static void Main() {
      new TestClass().Doit();
    }
  }

  public class TestClass {
    private MySocket mySocket;

    public void Doit() {
      for(var i=0; i<10; ++i) {
        using(mySocket) {
          mySocket=new MySocket(i);
        }
      }
    }
  }

  public class MySocket : IDisposable {
    private readonly int iteration;

    public MySocket(int iteration) {
      this.iteration=iteration;
      Debug.Print("Constructing "+iteration);
    }

    public void Dispose() {
      Debug.Print("Disposing "+iteration);
    }
  }
}

The output shows what is going on:

Constructing 0
Constructing 1
Disposing 0
Constructing 2
Disposing 1
Constructing 3
Disposing 2
Constructing 4
...

I'd probably advise just saying

using(var clientSocket=listeningSocket.Accept()) { ...

and getting rid of the clientSocket member variable altogether.

Also, if you don't mind me nitpicking, these two items are fields (taking up precious RAM) when they would be better off as constants. i.e. from

   int maxRequestSize = 1024;
   int portNumber = 80;

to

   const int maxRequestSize = 1024;
   const int portNumber = 80;


#10 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 09 November 2010 - 06:23 AM

That's not nitpicking, Corey. That's improving things. Thanks. I think portNumber could be set in the constructor so not constant, but readonly should be better there.

#11 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 27 November 2010 - 06:29 PM

I'll post the code later in the weekend but I'm so excited I had to let you know that I've now got the Netduino Plus webserver handing out files from the SD card. To be honest it isn't tricky, just a File.Exists() and a looped FileStream.Read / Socket.Send. However, there is something magical about seeing XML, XSL, CSS and JPG files being dished out by this tiny device and forming a (small) working web application. :D My home automation project now had a very basic HTML front end to let me truns a few lights on and open a garage door. Unfortunately I did this to postpone writing an Android front end, not realising that the Android webkit browser can't do client XSL transforms. Cool that it works in IE and Firefox though. Anyway, it's Saturday night so I've got to head out. Lucky I'm not a single man or I'd probably be trying to impress the ladies with talk of .NET microframework web servers and failing miserably. My wife tried her best, but she had to confess to notgetting what's I find so amazing about it.

#12 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 30 November 2010 - 10:56 PM

Attachment in first post updated. Now looks for a file on the SD card and sends it back. I've had this happily sending back XML, CSS and JPEG files of a few kb in size and providing a simple web UI to my project. I've not stress tested it, but I can't imagine it would like serving up anything too dramatic. Whilst it may act like a web server, streaming a HD video will probably not work!

#13 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 30 November 2010 - 11:20 PM

Bloody hell! I take that back! After posting I just had to test it. I added a couple more mime types and the little marvel happily served up a 25MB wmv (6 minutes to download) and a 15MB mp4 (in 4 minutes). About 60kb/sec is not quite streaming speeds but I'm still impressed. Increasing the fileBufferSize increased this to 95kb/sec and reduced those times.

#14 Omar (OZ)

Omar (OZ)

    Advanced Member

  • Members
  • PipPipPip
  • 564 posts
  • LocationPA, USA

Posted 01 December 2010 - 12:05 AM

This is awesome!
Bug fixes and new features magically appears without me doing anything! I gotta post more crappy code. Posted Image

Thanks Fred!
=Hari=

EDIT: Just looked at your code. Very nice! Clean and straightforward. Great job!

.... :lol:

Fred you did an AMAZING job with this code, much (x1000) times better than the "crappy code"(hari) I had posted. This is pretty awesome, I'll have to use it in the future... maybe it would be a good way to send data back to help with debugging...

Thanks for posting this :)
My Blog - Oz's Tutorials and Projects

Twitter - @ozsolutions
Youtube - VCSandARM

#15 Omar (OZ)

Omar (OZ)

    Advanced Member

  • Members
  • PipPipPip
  • 564 posts
  • LocationPA, USA

Posted 06 December 2010 - 01:48 AM

Here are some changes I made, maybe you'd like to support them in future updates:

        public class Listener : IDisposable
        {
            static bool go = true;
            static bool stopped = false;
            
            //....
        }

        public void StartListening()
        {
            while (go) // added a stopping system.
            {
                 // rest is the same
            }
            
            stopped = true;
        {

        public void Stop()
        {
            go = false;
        }

        public void Dispose()
        {
            if (listeningSocket != null && stopped) 
                 listeningSocket.Close();
        }

What this does is makes sure that there are no errors when trying to do a listen when things have been disposed... and it makes sure that we aren't listening at the moment that things are trying to get disposed. Uhm.. I don't know if it helps much, what do you think?
My Blog - Oz's Tutorials and Projects

Twitter - @ozsolutions
Youtube - VCSandARM

#16 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 06 December 2010 - 09:56 PM

Thanks. I'll add those in and include in any updates. My application just listens permanently so I didn't make that a priority.

#17 spur

spur

    Member

  • Members
  • PipPip
  • 27 posts

Posted 20 December 2010 - 07:33 PM

Awesome project, thanks for the great example :)


I had some issues getting it to work on an iphone over 3g. On my local wifi was no problem, but over 3g I had to add in a delay when it was trying to get the available bytes from the socket. This is probably not the best solution, but it seems to work. I added this to Listener.cs in the StartListening method.

                    int availableBytes = clientSocket.Available;

                    // iPhone on 3g needs some extra time here
                    int count = 100;
                    while (availableBytes == 0 &&
                        count > 0)
                    {
                        Thread.Sleep(1);
                        count--;
                        availableBytes = clientSocket.Available;
                    }

                    if (count != 100)
                    {
                        Debug.Print("Waited: " + (100 - count).ToString() + "ms");
                    }


#18 darkSol

darkSol

    Member

  • Members
  • PipPip
  • 12 posts

Posted 28 January 2011 - 03:13 PM

This works so great! I had to comment out all the Debug.Print's though because after running for a week on my local PC/network (NetduinoPlus RJ45 -> router, USB power to XP PC) my System process on Windows XP was maxed out to 98%, preventing almost anything else from happening. After drilling down into the processes it seems that the native Netduino USB driver was eating all the CPU. My theory is all the Debug.Print strings being pushed through USB back to the PC. It's a waaay older PC, circa 2002 so it only runs USB 1.0 ;) In any case it's been running for four days now (commented Debug.Prints) without incident. I can put the PC in sleep/standby mode and the NetduinoPlus is still powered up and serving pages! Kudos! Now if we could only serve up ASP.NET pages my life would be complete ;)

#19 Fred

Fred

    Advanced Member

  • Members
  • PipPipPip
  • 290 posts
  • LocationUK

Posted 28 January 2011 - 04:18 PM

I seem to get the odd connectivity issue that I can't seem to track down. Nothing a refresh doesn't sort out and I'm not sure if it's actually anything to do with the Netduino. I'm also not exactly sure how best to respond to some zero-length requests from IE - apparently probing for authentication. As far as the ASP.NET goes, the fun is writing your own. Not full-blown ASP.NET of course. I respond to ASP.NET MVC style request paths and send data back as hand-cranked XML or HTML. It's a bit like being thrown back into the dim and distant days of ASP's Response.Write and building up a string, but much more rewarding somehow.

#20 John Feeney

John Feeney

    Advanced Member

  • Members
  • PipPipPip
  • 55 posts
  • LocationAuburn, ON, Canada

Posted 29 January 2011 - 02:29 AM

I am just starting. I have a Netduino Plus. I have downloaded the code in the first post of this topic. I am using Visual Studio 2010. I hooked a network cable to the Netduino. In my Project menu, I wnet to the project options and set the Net Micro Framework Deployment to USB. When I run the code the blue onboard LED is blinking. (In main() I have set Thread.Sleep(500) to (5000) and I get a very slow blinking light....so I am sure that it is running ok). What I can't figure out is how I am suppose to talk with the Netduino? From a YouTube video I got the idea of pinging the Netduino. I beleive I am on the right cable. I ping 192.168.1.103 and I get back 4 packets sent and received. I don't have a miniSD card so, I changed the routine TrySendFile. I commented out the existing code and put in a Debug.Print("Testing...testing);. I also added using System.Diganostics to the top of the code. I am just coding in my home. We have one Linksys router with a couple of cables coming out of it. 1. How do you tell what IP address the Netduino is on? On my laptop I turned the wireless off, pluged the network cable into my Laptop and did a IPConfig. When I got back 103 I put it into the Netduino and turned my wireless back on. 2. If you have the correct IP address and the program in this post is loaded correctly, how do you send a command to the Netduino....Ulimatedly, I would like to make one of the programs where from a webpage or windows program they are turning the light on and off from the webpage buttons. .... but to start how can i get it to receive and acknowledge by executing the debug.print that i put in TrySendFile Thanks, John Feeney




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users

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