Web server and client in the same sketch?

First off, I understand almost nothing about networking, so please bear with me.

I'm producing a random sequence of 5 LED blinks on my Uno board. I have an ethernet shield connected to it, and I'm using a web server sketch to print out xml indicating which lights blinked (for instance: red, blue, red, green, yellow). It's printing out to a temporary web form, which suits my needs perfectly.

For now, of course, it just does this in a loop. But I would like to modify the sketch so that the Arduino server can receive an input which will tell it to produce another sequence. Whenever it receives the instruction, it should produce another blinking sequence. The instruction is going to come from a button click (in an Android application) which will perform a GET or POST or some such thing, and there will be some kind of PHP script on a server in the middle, I imagine.

What would be the best or easiest way to accomplish this on the Arduino side? Can my Arduino go back and forth being a client (doing an HTTP request, I guess) and a server in the same sketch? If that's even possible, would there be an awful time delay between the actions?

Any help you can give me would be greatly appreciated :slight_smile:

The Arduino can be both a client and a server, although that can be tricky to get working right.

It looks, though, like the server is the only thing you really need. The server serves up a form, instead of a static page. The user of the client that is showing the form enters some new values, and presses the submit button. The modified data is sent back to the server as a new request.

The initial request might look like:
GET / HTTP 1.0

When the submit button is pressed, the request might look like:
GET /?1=0&2=0&3=1&4=1&5=0 HTTP 1.0

The Arduino as server sees the two requests as different (one contains the ?; the other does not), and performs differently in response to each request. In one case, it simply returns data about each of the pins. In the other case, it uses the data in the request to set the pins appropriately AND returns data about each of the pins.

If the page being returned contains appropriate META tags, the client can periodically re-fetch data from the Arduino, so it can see what changes another client has made.

Thank you for your very clear and patient answer to my beginner's question.

Some combined server/client test code for the 0021 IDE.

//zoomkat 11-25-11
//simple button GET with iframe code
//for use with IDE 0021
//open serial monitor and send an e to test client and
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html 
//address will look like http://192.168.1.102:84/ when submited
//for use with W5100 based ethernet shields

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // ip in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
byte myserver[] = { 208, 104, 2, 86 }; // zoomkat web page
Server server(84); //server port
Client client(myserver, 80);
String readString; 

//////////////////////

void setup(){

  pinMode(5, OUTPUT); //pin selected to control
  Ethernet.begin(mac, ip, gateway, subnet);
  server.begin();
  Serial.begin(9600); 
  Serial.println("server/client test 11/25/11"); // so I can keep track of what is loaded
}

void loop(){
  // check for serial input
  if (Serial.available() > 0) 
  {
    byte inChar;
    inChar = Serial.read();
    if(inChar == 'e')
    {
      sendGET(); // call sendGET function
    }
  }  

  Client client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

            //now output HTML data header
          if(readString.indexOf('?') >=0) { //don't send new page
            client.println("HTTP/1.1 204 Zoomkat");
            client.println();
            client.println();  
          }
          else {
            client.println("HTTP/1.1 200 OK"); //send new page
            client.println("Content-Type: text/html");
            client.println();

            client.println("<HTML>");
            client.println("<HEAD>");
            client.println("<TITLE>Arduino GET test page</TITLE>");
            client.println("</HEAD>");
            client.println("<BODY>");

            client.println("<H1>Zoomkat's simple Arduino button</H1>");

            client.println("<a href=\"/?on\" target=\"inlineframe\">ON</a>"); 
            client.println("<a href=\"/?off\" target=\"inlineframe\">OFF</a>"); 

            //client.println("<IFRAME name=inlineframe src=\"res://D:/WINDOWS/dnserror.htm\" width=1 height=1\">");
            client.println("<IFRAME name=inlineframe style=\"display:none\" >");          
            client.println("</IFRAME>");

            client.println("</BODY>");
            client.println("</HTML>");
          }

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on") >0)//checks for on
          {
            digitalWrite(5, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(5, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
} 

//////////////////////////
void sendGET() //client function to send/receie GET request data.
{
  if (client.connect()) {
    Serial.println("connected");
    client.println("GET /~shb/arduino.txt HTTP/1.0");
    client.println();
  } 
  else {
    Serial.println("connection failed");
    Serial.println();
  }

  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read();
    Serial.print(c);
  }

  Serial.println();
  Serial.println("disconnecting.");
  Serial.println("==================");
  Serial.println();
  client.stop();

}