OVERALL HOME     Other material for programmers, not Arduino specific
ARDUINO: Top Page    Branch "A": Arduino Course    Branch "B": Arduino "How To"s and Projects
-d-Bookmark this on Delicious   Recommend to StumbleUpon

Microprocessors as Web Servers

With input and output across the web (or LAN)

This page is browser friendly, by the way. Make your browser's window less wide than your whole screen and you will find the narrower columns much easier to read. For more tips like that, see my Power Browsing hints.

Why this page??

I am an unashamed Arduino zealot, but this page is going to try to address some general points which should apply to using almost any microprocessor to set up a web server. Just be warned: I am a "one eyed king" as far as TCP/IP matters are concerned, although I have a reasonable background in the hardware and software of using Arduinos and clones.

What can you do?

With a fair bit of work, but not much money or equipment, you can set up a microprocessor to serve web pages. Or perhaps I should say "a web page" (more on this in a moment.)

A static (unchanging) page, to display "Hello World", is pretty easy, and a good place to start.

Once you have that working, you could easily proceed to a webserver that will report the state of inputs on your webserver. You could, for instance, interface your microprocessor to a temperature sensor, and then anyone visiting the served page could see the current temperature at the place where your server is.

And the ultimate goal, achievable, is to set things up so people out there in Internet Land can click buttons on the page your server sends them, and have something happen... whatever you've programmed the system to do... to the outputs of the microprocessor hosting the served page.

You can see such a system in action at one of my demos. The links to them are on my ArduServer-How to page. (A temperature sensor, readable across the internet, is a recent addition to the ArduServer2.)

What do you need?

(Apart from the patience of Job to get ALL the bits "right" so that things finally WORK

** Let's start with something you don't need: A "static IP address". And you don't (for now) need to know what one is!)

** You need an "always on", reasonably fast, internet connection. Many home users in the US and Europe now have a perfectly adequate connection. "Dial up" won't do. Sorry.

** Another thing you don't need: You don't need to leave a "big" PC, i.e. one running Windows, on all the time.... as long as your router can provide DynDNS updating. If not, you do need to leave your big computer running. But that really isn't such a big deal these days, with efficient machines. Trust me... if you aren't doing this now, once you start, you'll never go back to waiting for the thing to shut down, waiting for it to start up. And anyway, many routers are capable of DynDNS updating. (More on that later.)

** You need at least a smattering of knowledge of HTML "programming". You need to be able to put something like the following together....

      <title>My Web Page</title>
      <p>Hello World</p>

... but even THAT is more than you need! But the more you know about writing HTML, the more you will be able to do with your page.

** You will need some hardware to connect your microprocessor to your connection to the internet. Most people, I suspect, will use a LAN between that hardware and the router, and this "answer" has the bonus that you can start with something "easy", and then solve the next range of problems to take you to the ultimate destination. The "easy problem" is creating an intranet server, i.e. something which can give a webpage to other devices on your LAN. If you are going this route, then you need an "Ethernet interface" for your microprocessor.

** And of course you need the microprocessor to host the page! As I said, I use an Arduino, but much of what is in this page applies more generally.

My original, little ArduServer (ArduServer1) cost me about $40 for the microprocessor and Ethernet connection. My "big" one, ArduServer2, cost $55, 12/11.

The (longish) road to success....

First catch your rabbit. You need the various bits.

Become proficient on your microprocessor.

LAN "Hello World"

Once you have your microprocessor, know it is working, know how to work it: Connect your Ethernet interface, and try out the simplest web server demo you can find for it. All you need is something which will do the traditional "Hello World", across your LAN. I say "all"... even for that "simple" task you will have problems to solve.

One little "Gotcha" is that your server must have an IP address that nothing else on your LAN has. Likewise, it must have a unique (to your LAN) MAC address. ("Machine Access Control address.)

Neither is a "big deal", especially the MAC address, but you may have to tweak the demo code supplied for your system to fit your circumstances.

Getting "good" IP and MAC addresses is one of the many "little things" you will come across on this journey which "shouldn't" be a problem, but can be.

Your LAN probably has DHCP services running out of your router. To be thorough, it is probably worth telling your router not to use a whole block of IP addresses for dynamic allocation. (This "dynamic" has almost nothing to do with "DynDNS", by the way.). And then use one of the IP addresses outside of that range for your Ethernet interface. In my case, for instance, my router issues IP addresses from to via DHCP, and never issues any others. That means it is "safe" for me to make the IP address of my microprocessor as long as I haven't also allocated that IP address to something else on my LAN.

The chance of your Ethernet interface having the same MAC address as something else on your LAN is vanishingly small... and so why does it happen so often? Happily, all of the Ethernet interfaces for microprocessors I know about let you assign whatever MAC address you wish to the interface.

This becomes non-academic immediately if you elect to put two microprocessor-driven Ethernet interfaces on one LAN. You would have to make at least one tweak to the software in the second one, so that it used a different MAC address.

While on the subject of IP addresses, etc, I'll touch on and then forever hide from the topic of the anti-malware (viruses, etc) defenses which I hope you have running on your system... It will have to be made happy about this new device you are introducing. I haven't had too much trouble over this, but it is an area which can cause trouble. Don't forget that you may have a firewall running in your router as part of your anti-malware defenses.

Wikipedia is safe for now

When I started out to create my first webserver, I already had dozens of pages published on the internet, which were held on a commercial service's server, saving me all those headaches.

Then I built my first PC based server. That was an adventure, too. Today, WAMP and the like make it so VERY much easier to set up your own server, if you're willing to have it run in a PC.

At that point, I thought of a web server as a "box" which took care of serving up pages of "stuff", pages which were stored on the server as separate files. The page you are reading now resides on a server maintained by 1&1, for instance.

So how do we supply a bunch of files to a microprocessor? The (first... and only one, I have, so far) answer is: We don't

The sort of "web page serving" I know how to do with a microprocessor is limited to serving one page, a page hardcoded in the program that does the serving.

That isn't a complete disaster, because the page can be a little dynamic. For instance, it can show the temperature as detected by a sensor connected to the microprocessor.

And another thing... the page can't be very large... at least with the systems I've been playing with. The following pretty well filled a system I built... but after you glance at it, read on to some good news...

ArduServer2, ver 1 Jan 12d

See ArduServer.com

Cmnds: ?cmd=0 and ?cmd=1
Add "/?cmd=1" to page URL for different text here.

- -

Temperature, degrees C: 16.53

- -

Analog input 0 reads: 262
Connected to a phototransistor.

Light in room: dim.

- -
Analog input 1, senses LED light, reads: 73

Remember: This is just a screenshot... buttons don't work here.

Clicks since ArduServer booted: 124


STOP PRESS: It seems that maybe there's an element of bad advice in some of the pages this is connected to.

It may be a bad idea to use any of the following at the same time as a W5100 based shield... although for a "Pro Ethernet" it seems that only D10-D13 should be avoided. I am working on a similar list for ENC28J60 interfaces... it seems it might be the same as the list below, minus D4, An0 and An1... but your work might as well be W5100 friendly, too, don't you think?

... and D13, but this last one only if you "care" that on the shield it goes to an LED, and from there through a resistor to ground. (This merely parallels the same thing on many Arduino and clone boards... BUT, to digress from the digression, BE AWARE that the software behind "setup()" and "loop()" pulse D13 high briefly before executing whatever you specified in "setup()".)

Of course, I unwittingly used some of those lines in my designs. The designs SEEM to work, but it would be a good idea to take what I've put on those lines and move them elsewhere. I will gradually be revising my designs as follows....

(I've done a separate page with help on the support hardware, including a PCB design for a suitable shield.)

In every case, to modify the software is easy... but you will need to look carefully to see whether what is currently online has been modified or not.

To change the line used for, say, the phototransistor watching the LED in, say, ArduServer2, the line....

client.print("<br>Analog input 0 reads: <b>");

... must be changed to...

client.print("<br>Analog input 1 reads: <b>");

... and you are done! (You'll have to move one wire on your breadboard, too, if you had it wired for the original design.)

(Digression: Is nothing every easy? In 99.0% of my code, such a change would merely have been a matter of changing something like the "const byte bLEDpin=8;" at the start of the program. But in this case, to avoid fighting with... not hard... getting the prompt to identify the channel, I took a shortcut and specified the channel explicitly instead of a global variable. Sigh.

Sorry! I could have done without this, too! When will the Official Arduino Site have proper documentation of the ethernet shield and library?? I am working on getting all my pages converted to the "new standard"... in the meantime, you'll just have to stay alert!

So. Do you see why I headed this section "Wikipedia safe"? You won't with a simple microprocessor server publish vast amounts of information... but you will be able to publish your information. And, if you wish, control things around the microprocessor from any internet terminal.

The good news is that the little page I showed you above, in real life, has a graphic in place of the text "IMAGE DISPLAYING HITS". It shows the place people were in when they visited the page, it lists the countries people visited from and it shows any current visitors. It is a free service from RevolverMaps.com. In order to have the Revolver Map on my page, I had to insert about 650 characters into the page, characters which could have been used for other things, had I wished.

By the way... again... Another thought for you: A simple microprocessor based web server is not going to have layers of security. I would assume that anything you can do via your server, other people can do, too. I don't mind people playing with the LEDs I have connected to my ArduServer... but I'm not going, say, to establish a way to unlock my front door across the internet just yet. (I unlock my front door with an RFID tag in my watchstrap... but I (or at least my watch) has to be there for that to happen.)

Understand the workings of "the internet"

As you are reading this page, I gather that you able to put a URL (the "www- thingie") into a browser (Firefox, Chrome, etc). But how much do you know about how it all works?

You're going to have to know (or learn) a bit, if you want to set up a microprocessor server. Sorry.

When you put, say, http://sheepdogsoftware.co.uk, into your browser, some amazing stuff goes on. I'll try to contain myself to the essentials.

First of all, "the system" translates the sheepdogsoftware.co.uk into a "number", something like If that were the actual number (I just made something up), then the server for sheepdogsoftware.co.uk is (for the moment) at IP address. The site is mine, but I don't know where the server for it is just now, as I pay 1&1 to take care of that problem for me.

You're going to need an address for your microprocessor based server... but it is both complicated and not complicated.

The "not complicated" part of it first:

Your server is going to "talk to" the outside world through your router. The router and your server will be talking to one another across a LAN, or at least a link that looks like a one station LAN. The address for the server, at that level, will be something like

Initially, I would suggest that you get things working just within the LAN... Fire up a browser in a PC connected to the LAN, put the server's local IP address in, and you should see the page the server serves. If you don't, fix whatever problems are in the way, because they'll still be there when you try the fancier things later, and still stop you succeeding.

Your router shows a different IP address to the outside world. Unless you have a static IP address for that, and you will know, from the pain of paying the bill, your router talks to the outside world with a dynamic IP address. It may not change very often, but it does change, whenever it suits your internet service provider.

Can you see where this is going? Put together the things I've said recently.

Eventually, you will have a URL for your microprocessor server. Let's say it is MyServer.com. "The system" (outside your LAN) has a mechanism which looks up things like sheepdogsoftware.co.uk an MyServer.com in "directories", and sends back the IP address for the submitted URL. Your browser then uses the IP address to contact the server. (If you happened to know the IP address, you could access the server with that... but you don't usually know it.)

The part of the system that translates URLs to numbers is called the DNS (Domain Name System).

A little digression: There are two "IP addresses" coming into this discourse: The "outside" IP address, the one the router uses with the outside world, and the IP addresses of the devices in your LAN. For the moment, I am talking mostly about the outside IP address.

So there's the DNS. It is like a telephone directory. If sheepdogsoftware.co.uk were actually at, as long as it stayed at that IP address, and as long as somewhere along the line the DNS was told that was the IP address for that URL, then all would be fine.

So what happens when my ISP gives me a new IP address? My site, sheepdogsoftware.co.uk, is no longer at the old IP address. Disaster. My hosting service has either to pay for a static address, or keep track of any changes, and tell the DNS about them.

When you not only edit your pages, but also directly manage the server that they come from, you have to start dealing with the IP address issue.

Happily, there's an answer.


DynDNS.org is not the only organization offering the service I am about to describe, but it is the one I "know and love", and can recommend.

This is what they do...

You sign up with them and they will give you a URL. (You can't just make up whatever URL you want... the allocation of names is controlled... globally. It wouldn't work to have two sheepdogsoftware.co.uk's, would it? Which one would be displayed in the browser of someone who went to "the" sheepdogsoftware.co.uk page?

"Your" name, if provided for free by DynDNS.org will be a little constrained. I have two, and, by my choice, they are both sub-domains of DynDNS.org...


("mon" as in "monitor", and "277rr" and "7nc" because that tells me what is monitored by the web pages attached to those URLs.)

Here's the magic bit: Either a PC connected to your router, or your router, if it is clever enough, constantly (well... every so often) checks what (outside) IP address is currently allocated to you by your ISP. When that allocation changes, your PC or your router send a message to DynDNS, who then send a message to the DNS, and your entry in the DNS tables gets updated. Cool! And while you probably don't fully understand all of that now, I'm leaving further discussion to the innards of the detail led tutorials about setting up servers, apart from two things...

a) "DynDNS" stands for "Dynamic DNS".

b) We've been talking about the "outside" IP address. What about the LAN IP address of your server?

Before I address that, I want to look at "What about the LAN IP address of the PC you are using to access the internet? Assuming you are accessing it though a router, which you are accessing across a LAN, be it wired or wireless.

Here's what happens...

You ask for the page at sheepdogsoftware.co.uk.

A message, flagged with your PC's local (LAN) IP address, goes to the router. The router "makes a note" as to what's going on, and presents the request for sheepdogsoftware.co.uk via the router's external IP address

In due course, the answer comes back, again via the router's external connections, external IP address. However, the router has a way of knowing that this answer is for your PC, and so passes it on to your PC, again using that PC's LAN IP address.

Good news: You won't have to deal directly with these things (much)... but you may need to know them to deal with "stuff" as you proceed towards having a working server online!

So. We're getting there. You know about the parts which have to be connected. You know about the IP address for connecting over the LAN to your router, you know that it needs an external IP address, and a URL which the DNS knows about. And you know how to maintain the DNS's idea of "where" your server is, even though the address may change from time to time.

Hello (Internet) World

Whatever microprocessor and Ethernet interface you are using, there should be a "Hello World" example online for you to start from.

For the Arduino with the "standard" Ethernet Shield, there's a demo called "WebServer" in the Ethernet folder of the Examples which you can access from the File menu item. (At least there was with Arduino.exe 0022, which was current when I wrote this in August 2011.

Get the (local) IP address issues, sketched above, taken care of, and you should be able to see the demo's "Hello World" across your LAN without much ado. You don't need to worry about DNS, the outside IP address, DynDNS, etc., for that.

Once you can see the "Hello World" demo locally, get yourself a DynDNS URL, and overcome whatever little "joys" await your want (if "need" can be a noun, "want" can be a noun!) to see that "Hello World" by entering a URL. Just to be on the safe side, phone some friends. See if they can see your server's "Hello World" from where they are. (Sometimes when you use a URL from within a LAN, if the URL shares the same outside IP address as PC seeking the page, you can get experiences people outside your LAN don't get. You should both see the same thing.)

Whew! Whew! Whew! Whew! WHEW!

Exhausted? No? Then you've only skimmed the above. And not tried to do any of it in practice. If ever there were a battleground filled with detail devils, what we've been talking about is it.

But there's good news again!!!

Once you've got this far, the rest of our journey is relatively "easy". If you have a "Hello World" server running, which can be seen from anywhere on the internet, you've got past the worst bits, and got well past half way.

The software

Now it is time to delve into the software, and how it all works.

In a nutshell, your server....

(So far, our reply is the stuff needed to put "Hello World" on the recipient's screen, when the html is "fed" to a browser.)

The stuff needed to put "Hello World" on the recipient's screen...

You might get away with nothing more than a few header lines and "Hello World".

It would be better to send the header lines, plus at least....

      <p>Hello World</p>

There are many guides to writing HTML out there on the internet. Don't worry... you can ignore them for now! But when you are ready to make your page nice, learn some HTML.

A digression... a different comms scheme

Before I take you through an outline of how things pass between computers across the internet, I want to talk about something similar, but older. Then I will return to what I was saying just now, explain more of it.

Once upon a time, if we wanted to connect two computers, we did it with a serial cable... and you can still do that today.

For those computers to "talk" here's how things were often done...

Each had a "buffer". When things arrived from the other computer, they went first and immediately to the buffer. The receiving computer dealt with them, from the buffer, when it "felt like it". As long as mechanisms were in place to ensure that neither buffer became too full, all was well.

Doing such things with an Arduino as one side of the "conversation" (or two Arduinos talking to one another) isn't too difficult. I wrote some web pages about serial communications with Arduinos.

In general, programs for such comms have a few "housekeeping" odds and ends to do once, as the program is starting, and then something like...

scMySerialConnection.print('Hello World');

.. is enough to send the text off to the other computer's serial input buffer, where it sits quietly until processed.

Sits quietly until processed...

So much for how things are sent. What happens at the receiving end. We're still talking about serial comms... internet interactions are to follow.

A program for having two computers "talk together" is either going to have an event handler which is triggered by incoming characters, or, in the case of the less complicated microprocessor world, a loop with the following, at a minimum, in it. (The loop will probably have other things, such as code to look at what was received, and behave accordingly... if only "behave" as far as putting what was received on a screen the human user can view.

if (scMySerialConnection.NotEmpty)
    //use byte somehow

The two hypothetical things in that, NotEmpty and DeliverByte will be things that are provided, somehow, by the particular software and libraries you are using in your environment.

The first returns a boolean "true" or "false", depending on whether there is something waiting in the receive buffer. The second takes the oldest byte out of the buffer, and puts it in bTmp, in the code above.

The "use byte" part may well involve collecting up several bytes into an array or string, and processing the whole message once it has arrived. How do you know it has arrived? Either by arranging things so that all messages are of the same length, or by having some character set aside to "say" "that's it, message complete."

So... that's life when you're doing serial comms.

Internet Comms

I may be abusing the terms slightly, but I think the right name for what I've called "internet comms" is TCP/IP: "Transmission Control Protocol / Internet Protocol"

"Protocol" means "rules, ways of doing things".

Our serial comms example wasn't trivial, but it was helped by a few things. It could have been worse... but it was limited. TCP/IP is "worse".... but it is worth it, for the extra fun it gives you!

Serial comms, as described above, was for Computer A to talk to Computer B, over an already established, always available, "private" channel.

With TCP/IP, there may be more than two computers, but more than two at the same time is an "advanced" topic for another time. However, even for the simple things we'll discuss here, while it will be two computers at a time, the computer from out there in Internet Land which is talking to your server today may well be different from the one which was talking to it yesterday.

All a bit more complex than the simple two- computers- wired- together of the serial comms case. And so, I fear, a slightly more complex scenario... but don't worry! Serial wasn't too complex, and TCP/IP remains do- able.

An aside: In the simple scenario we are dealing with here, the two computers in "conversation" do not "remember" each other, beyond the following:

Computer "A" says to Computer "B", "Please send me the page called GoodStuff.htm". Computer B "remembers" Computer A just long enough to respond. If A asks for some further information a moment later, B doesn't "realize" that they've talked before. And our little microprocessor driven server can't even accept a request for a specific page... it can only send one (fairly small) page.... but the page's content is dynamic, which makes all the difference.

Simple software for web page serving

If you visit either of my pages with code for Arduino based web servers, you may be daunted by the sourcecode.

You don't need to be. The code isn't as bad as it looks.

The following is a bit general, and I don't even promise that it is 100% correct... but these are the concepts which got me to the end of programming my working ArduServers. (There are two primarily so that I could explore the pros and cons of two different Ethernet interfaces.

First, as with the programs for serial comms, there are a few things which must be done once at the start of the program's execution, to "set the scene" for the communications. In the case of the programs for serial comms, one of the things you did once at the beginning was to inform the routines you would use of the baud rate you wanted. In the case of the programs for TCP/IP you will inform the routines of the IP address and MAC address to be used.

The IP address I am speaking of here is the local, or internal, IP address. The one used to locate your server within your LAN, the address which probably starts 192.168...

Neither you nor your program needs to know what "outside" IP address the router is using to pass on your requests to the outside world, and receive the answers... which it passes back to you via the local IP address.

With TCP/IP programming things are a little more complex that the programming for the serial comms.

The main "do it again and again" part of your server program watches out for an incoming request. Should one be seen, a "connection" is set up, and the request flows into buffers. In some cases, you will send an answer back, via the connection. In any case, not long after the process started, the connection will be shut down again.

(I am really "winging it" there... if any experts would be good enough to send me constructive criticism, I would be delighted to improve the above, as necessary!!)

That, as best as my limited knowledge permits, re-covers the idea of "the program watches for someone to come knocking at the door"

All I know about handling so far is a "GET" request... but that's okay, because it is "GET requests" that browsers send.

I you look into the code for ArduServer2, you will see that the authors of the program I based that on say that you can tell when a page request has come in, because the last line (before you run out of sent stuff) will be a blank line. Their code watches for this, and if it sees it, it assumed a GET request(?) and moves on to responding to it.

My own researches suggested that the "stuff" sent with a GET request included a line which might look like...

GET / HTTP/1.1

The demo code I adapted already ignored requests which didn't end with a blank line. I added monitoring of a certain character within the "GET" line... more on this later.

My reply... it's a bit scrumpled...

Recognize the quote? (Not important if you don't)

So... we've talked through the early stages of a TCP/IP interaction. Assuming everything points to the need for a reply, how do we go about that?

Happily, in both of the ArduServer programs I've written, you just do a bunch of lines a bit like....

printtolan('<p>Hello World</p>);

The word isn't actually "printtolan", but the code fragment above illustrates what you are going to do.

It is a little strange, at first, writing the web page text (in HTML) while at the same time writing the program code, in a second language.

Be that as it may... deep within your server program is a block of code which, in essence, is just a bunch of "print" statements filled with HTML.

Depending on your environment, you may be able to pass things other than strings to the web page. Suppose, for instance, in your program you had a variable called wClicksSoFar, holding the number of clicks seen by the server since it was last booted. You could almost certainly do the equivalent of...

(If your "printtolan" isn't very clever, you might have to do something extra to turn the number in wClicksSoFar into a string, but that isn't necessary in the Arduino language... not, at least, the language for the W5100 Ethernet interface. (I don't recall if what you use for the Microchip ENC28J60 is as capable. I think it is.)

As long as you have everything "ready" before you get to the block of code with all the "printtolan" statements, much more is possible. You could, for a simple instance, expand the above to...

printtolan('<p>Clicks so far: ');

if (wClicksSoFar<100){
  printtolan('Where is everyone?');
  else {
  printtolan('More than 100 clicks served!');


That's a largely facetious example... but it will do. Just don't underestimate the power of the facility illustrated.

If you can report what is in wClicksSoFar, as illustrated above, you can use your microprocessor's I/O capabilities to sense the things connected to it, and include that information in the page served.

The Arduino has, built in, the hardware and software for ADC... analog to digital conversion.

You can put a light sensor on, say, Analog0, and then have in your page...

printtolan('<p>Reading of light on sensor: ');

There are many variations possible on these themes... I hope I have got you thinking about all the creative things you can do, now that you realize where to but the code behind the stuff the user of the server sees.

A little detail...

Some correct (if simple) HTML headers are shown in the code above. There are more headers, which are seen by the server, which arrive before the HTML headers. In addition to the lines already given, before them, when replying to a GET request, you need to send (by the same mechanism)....

printtolan('HTTP/1.1 200 OK');
printtolan('Content-Type: text/html');

We're "halfway" there... but don't panic...

I meant "halfway" in the sense of we have covered how to accomplish one of our two goals: A webpage with dynamic content, reporting on what is seen at the microprocessor's inputs.

Happily, in building that, we took care of lots of things needed to allow users of the server to send it "inputs", so we are way beyond half way through the text of this tutorial. And thanking our lucky microchips that this is the cases!

Send in the... not the clowns... Send in your inputs

Now we will turn to how you set things up so that the person viewing the page served by your microprocessor can cause outputs of the microprocessor to change.

When I think how many years I was perplexed by this, it is aggravating that it really is very simple. (When you know how).

The first thing you need to know is that if, into the address bar of your browser, you enter, say...


... two things will happen. First all the complex magic of fetching the page at Sheepdog Software about sensing and control work will be returned to your browser.

In addition, the "?HiSheepdog" part will be available to the server. In most cases, it will just be thrown away, especially if you pass something unexpected. But it doesn't have to be thrown away.

I'm going to refer to the bit on the end as the user command.

Once you know that, two questions arise:

Sending User Commands

You can, of course, be pedestrian and just type them into your browser's address bar (where URLs go) by hand. And sometimes this is The Way To Go.

You can help users of your site by creating links which include the appropriate user command. Here is some HTML to illustrate the point. You can't click on these, here. If they were "inside" a page, they would create clickable links which would do what they say, assuming there was a server at MyServer with an LED set up to turn on with the commands shown...

<a href="http://MyServer.com/MainPg.htm?SetLEDOn">Turn LED On</a>
<a href="http://MyServer.com/MainPg.htm/?SetLEDOff">Turn LED Off</a>

(All the user would see would be two links: "Turn LED On" and "Turn LED Off")

Now prepare yourself for, perhaps, some minor mental gymnastics. Although some will say that what I'm going to show you is "obvious", I don't think everyone will think so.

What would happen if the links above were on the "MainPg.htm" page of MyServer.com?

Yes! The link would re-load MainPg.htm, but with the user command passed to the server as well.


Of course, in our simple microprocessor based web serving, we don't have the luxury of multiple pages at our sites. No problem. We just have to adapt the above slightly. If the page at MyMicroServer.com, served by a microprocessor, had the link...

<a href="http://MyMicroServer.com/?cmd=SetLEDOn">Turn LED On</a>

.. then that link would reload the single page that MyMicroServer.com would load, but the user command "?cmd=SetLEDOn" would be passed to the server at the same time as the request for the page.

There's nothing "special" about the text "?cmd=". The computer doesn't "know" what it means. But for the next thing we'll discuss, buttons, it is easier if the user command is in two parts joined by an equals sign.

The question mark is at least traditional, and may be necessary in some circumstances, so I'm putting one in, just in case.

So far so good, so adequate. But "I want a button!", I hear you cry. "Links are so... basic."

I was mystified by buttons, and the forms that deliver them. I still know next to nothing about them. But in the demo for the nuElectronics Ethernet Shield I saw a button used as follows. It really doesn't do more than create a button to make the request made by the link we have just discussed. Again, what you see below is the HTML to go into a page.

<form METHOD=get action="http://MyMicroServer.com/">
<input type=hidden name="cmd" value="SetLEDOn">
<input type=submit value="Turn LED On">

Inserting that in your page's HTML creates a button with "Turn LED On" on it. When you click the button, it will be as if you had entered....


Into your browser's address bar.

Using User Commands

When your server begins to process a request from a browser, it not only receives the user command, if any, sent from the browser, but a whole bunch of other stuff arrives as well. Here is a sample of what a server at MyMicroServer.com might receive if a browser asked for what http://MyMicroServer.com is serving:

GET / HTTP/1.1
Host: MyMicroServer.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1;
    en-US; rv: Gecko/20110614 Firefox/3.6.18
    ( .NET CLR 3.5.30729; .NET4.0C)
Accept: text/html,application/xhtml+xml,
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive

The only part of that which interests us for our needs is the "GET" line.

If the user had entered http://MyMicroServer.com/?cmd=SetLEDOn, then the GET line would be....

GET /?cmd=SetLEDOn HTTP/1.1

That's most of "the secret" of handling user commands. The rest is just tedious detail.

You need to locate the part of your system where what is coming in from the requester is fetched. In simple applications, the program is probably just fetching a character from a buffer, and another, and another, etc, until the buffer is empty.

To process user commands, you need to watch that stream of characters. I think you can rely on the GET being the first line of the message you might want to respond to. I hadn't thought of that when I created ArduServe2 from the standard (at 7/11) Arduino "WebServer" demo. In my program I looked at each line as it came in, and saved the most recent one to begin with "GET". (I don't expect there would be more than one, but what the program and the system does is always more important that what you are assuming.)

I waited until all of the request had arrived, and then, just before generating the response, I looked at what was in the GET line.

I cheated. Instead of looking at the line in detail, I only looked at the 10th character. As I had specified that the commands I would process were...

... or...

... I could just look at the 11th character in....

   GET /?cmd=0 HTTP/1.1/
... or...
   GET /?cmd=0 HTTP/1.1/
... or...
   GET / HTTP/1.1/

.. and act on whether I saw a 0 or a 1 or a /, the latter arising when the user did not supply a user command.

This crude answer is fraught with ways to go wrong when you try to extend the program... but it works for simple needs!

Two servers on one IP address: The magic of ports

Many of you won't need this little additional gem... but if you already have a server on your internet connection, this is how you can set up another, without disturbing the first.

When I said "server" just now, I meant a server which is accessible from the outside world.

As we discussed elsewhere, people in the outside world will access your server with a URL... "MyServer.com", or somesuch. Probably something arcane. One of my servers, for instance, is accessed via


Somehow... in my case, with a little help from the nice people at DynDNS.org, the DNS has an internet address for every URL on the planet. At the moment, the IP address for the above is, for instance. But that could have changed by the time you read this. I don't care, though, because everything is set up to deal with those issues automatically. Now. And I've told you elsewhere how to get things set up thus.

When someone sends a request to http://mon277rr.dyndns.org/, that request turns up on the "outside" half of my router. It then forwards the request to a computer on my LAN, at some address like That computer is running the server which delivers my FarWatch pages. The computer assembles what is needed, passes it to the router, over The router sends the material off to whoever asked for it via, at the moment,

How do I put an ArduServer on my LAN "along side" of the FarWatch server? How to I make FarWatch's traffic go to the FarWatch server, and the ArduServer traffic go there.

It is all about "ports".

The default port for http is port 80. You can say, explicitly, that you want to talk on port 80 by adding ":80" to the end of the URL, like so:


... but there'd be no reason to.

"Port": In citizen band radio terms, it is a bit like a "channel".

If you put the following into your browser...


... the browser will send a "GET" request to the same IP address, but it will add "And please see what is available on port 81" to the request.

On many servers, nothing will be available on port 81. When I tried...


...I was told "Firefox can't establish a connection to the server at bbc.co.uk:81"

Fair enough. No reason for the BBC to offer us a second treasure trove of good web pages via a second port.

However, for me, with my single external IP address and a want to put two servers online, ports were the answer.

Have a think... what needs to be tweaked to make it all work? We want the computer on to serve all requests for the FarWatch server, and the Arduino, on to handle the requests for the ArduServer. Who 'ya gonna call??

(answer further down page....)

Have you thought about it?


Come on! What's your answer?

I've given you several clues. Answer coming up... don't scroll down until you've framed your own answer.


Did you say the magic is in the router? Well done you, if so!

The details of how you say "Send any http traffic for port 81 to local computer" vary from router to router, of course. You don't need to utilize the unnecessarily powerful "DMZ" features of some routers. You don't need to get into the complications of VPNs. What you want to do isn't rocket science. Beware: Your anti-malware system may baulk at sending things to a non-standard port until you tell the system that you don't mind.

Finally, because you've been good, I have put the full code for the ArduServer2, the device presented in this tutorial, on a separate page for you.

That is the sourcecode for setting up a server in an Arduino connected to a "new" (at 7/11) Arduino Ethernet shield, one of the ones based on the W5100 Ethernet controller.

This code will be moved to a page with a discussion of it's specifics in due course. For now, here it is, even if it isn't in the right place, or explained in detail. All of the above is explanation of what is in that code.

(I offer a page about choosing and connecting light level sensors, if you want help with that.)

I hope that was useful...

I hope that was useful. Please let me know if there are areas where you are "stuck"... at least "stuck" at the "what is the question?" stage. For details of Making It Work, if you are an Arduino user, I have other pages for you. If you work with a different microprocessor, you will need to turn to your own community for specifics.

Please remember that the information here is entirely unofficial.

Search for other things...

Please note that I have two other sites, and that the following search will not include them. They have their own search buttons.

My Sheepdog Guides site.
My Arunet site.

   Search this site or the web        powered by FreeFind
  Site search Web search
Site Map    What's New    Search
The search engine merely looks for the words you type, so....
*    Spell them properly.
*    Don't bother with "How do I get rich?" That will merely return pages with "how", "do", "I"....

You can also search this site without using forms.
Ad from page's editor: Yes.. I do enjoy compiling these things for you... hope they are helpful. However.. this doesn't pay my bills!!! If you find this stuff useful, (and you run an MS-DOS or Windows PC) please visit my freeware and shareware page, download something, and circulate it for me? Links on your page to this page would also be appreciated!
Click here to visit editor's freeware, shareware page.

Want a site hosted, or email? You can also help me if you sign up via this link to 1&1's services. (I wouldn't recommend them unless I was happy after several years as one of their customers, but yes, they do pay me if you use this link! As do the Google advertisers, about whom I know nothing, of course.)

Valid HTML 4.01 Transitional Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org

CSS behind the page checked, at least once upon a time!, with http://jigsaw.w3.org/css-validator/
Why does this page cause a script to run? Because of the Google panels, and the code for the search button. Also, I have some of my pages' traffic monitored for me by eXTReMe tracker. They offer a free tracker. If you want to try one, check out their site. Why do I mention the script? Be sure you know all you need to about spyware.

Editor's Main Homepage
How to email or write this page's editor, Tom Boyd

....... P a g e . . . E n d s .....