Hmm...why isn't this working? See any obvious errors?

I’m trying to set up an ethernet webserver, so when a client goes to [myip]/pigs.htm it serves up pigs.htm. My code compiled without errors, but firefox seems to get stuck at an infinite loop. The SD works, it reads the data. When I inserted Serial.print() into my code after client.print(), it shows random numbers(seemingly) in the console. Of course, you wan’t my code, so here it is: EDIT: Check for the updated code later in the thread…

#include <SPI.h>     //The SPI Bus
#include <Ethernet.h>//Ethernet Chip stuff
#include <SD.h>      //SD Card
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Unique identifier that...I can pick!
IPAddress ip(192,168,1,145); //IP Adress that...I picked!
EthernetServer server(80); //It's important.
char current; //Current Parsing Char
char FileName[8]; //You'll see
int x; //A number

void setup()
{
  Serial.begin(57600); //Starts up the Serial at a baud rate of 9600
  Ethernet.begin(mac, ip); //Starts the Ethernet connection
  server.begin(); //Boot! //Begins the server
  SD.begin(4); //Start reading from that SD Card there
  pinMode(4, OUTPUT); //Important for SD sheild
  Serial.print("IP is at: "); //Prints that text
  Serial.println(ip); //Prints the IP
}
void loop() {
  EthernetClient client = server.available();
  if(client) { //Anyone Home?
    Serial.println("\nRequest Recieved!");
    while (client.connected()) {
      char Packet[client.available()];
      if (client.available()) {
        char c;
        for(int x = 0; c != '/n' && x<22; x++) {
          c = client.read();
          Packet[x] = c;
        }
        if(Packet[0] == 'G' && Packet[1] == 'E' && Packet[2] == 'T') {
          for(x=5; current != ' '; x++)
          {
            FileName[x-5] = Packet[x];
            current = Packet[x+1];
          }
        }
        Serial.println();
        Serial.println("File name is: ");
        Serial.println(FileName);
        if(FileName == " HTTP/1. ") {
          File myFile=SD.open("hom.htm");
          if(myFile) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println("<!DOCTYPE HTML>");
            while(myFile.available()) {
              client.print(myFile.read());
              Serial.print(myFile.read()); //<--There!
            }
            myFile.close();
          }
        }
        File myFile=SD.open(FileName);
        if(myFile) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          while(myFile.available()) {
            client.print(myFile.read());
          }
          myFile.close();
        }
        else {
          Serial.println("Oh Fiddlesticks!");
          Serial.println("Something is broken:");
          Serial.println();
          Serial.println();
          if(!SD.exists(FileName)) {
            Serial.println("Oops! It seems that that file doesn't exist!");
            Serial.println();
            Serial.println();
            client.println("HTTP/1.1 404 NOT FOUND");
            client.println("Connection: close");
          }
        }
      }
    }
  }
}

Again., the connection is made, but firefox doesn’t seem to understand the arduino…why?
Here’s a pastie link for those who enjoy Syntax Highlighting
http://pastie.org/8798270

Without reading the code, let me ask: have you tried IE? if none of your browsers can load the page, then your code has some problems. But, some browsers tend to ask for favicon when then first load a page, which is probably unexpected by your server. FYI, this favicon is the icon that displays on most browser tab corners, a square icon to indicate what website you are on.

You should have started with a library example sketch, not your own.

The following makes no sense:
I added my comments to your code.

    while (client.connected()) {
      char Packet[client.available()]; // This is a bad way! Define a fixed length array outside loop as the maximal bytes you can receive. Even if this works, you will erase anything you previously stored when the while loop enters the next iteration
      if (client.available()) {
        char c; // Why is c not assigned any value?
        for(int x = 0; c != '/n' && x<22; x++) { // With a for loop?! How can you be sure you received all client's response, instead of partial?
          c = client.read();
          Packet[x] = c;
        }
          if(!SD.exists(FileName)) {
            Serial.println("Oops! It seems that that file doesn't exist!"); // Why not printing out the file name to see what was requested, such as the favicon.ico that everybody is requesting at first visit?!

Unfortunately, IE behaves the same as firefox. It tries to connect, the ethernet shield tries to give me a seizure with it’s TX and RX lights, and after they stop IE still sits. Perhaps it’s sending the character CODES (ie 87 = W) instead of the letters. The serial monitor seemed to list char codes, so that’s what makes me think…good idea, I forgot about favicons, but I think that FF wouldn’t have that kind of thing in it. Why compromise an entire page just because the favicon doesn’t work? Thanks anyway.

liudr:
You should have started with a library example sketch, not your own.

The following makes no sense:
I added my comments to your code.

    while (client.connected()) {

char Packet[client.available()]; // This is a bad way! Define a fixed length array outside loop as the maximal bytes you can receive. Even if this works, you will erase anything you previously stored when the while loop enters the next iteration
     if (client.available()) {
       char c; // Why is c not assigned any value?
       for(int x = 0; c != ‘/n’ && x<22; x++) { // With a for loop?! How can you be sure you received all client’s response, instead of partial?
         c = client.read();
         Packet = c;
       }






if(!SD.exists(FileName)) {
           Serial.println(“Oops! It seems that that file doesn’t exist!”); // Why not printing out the file name to see what was requested, such as the favicon.ico that everybody is requesting at first visit?!

c isn’t assigned a value until the for loop, and the file name is printed out somewhere along the lines…It wasn’t favicon. The examples way of doing it didn’t make sense, I can just add a delay because i only need the first GET part. I don’t care if they use FF or Chrome Or IE or Opera or Mobile or Duck or PotatOS. The problem, I think, lies in the Transmitting part of the code, since that returned the proper filename for me.

liudr:

char c; // Why is c not assigned any value?

for(int x = 0; c != ‘/n’ && x<22; x++) { // With a for loop?! How can you be sure you received all client’s response, instead of partial?

The loop itself parses the string as it comes in…client.read() returns the last character.

The variable c was used in for statement without first obtaining a value. That is not correct.

What you should have done is to receive all of the HTTP headers before sending back what's requested. Also, print every character as you receive them, so you know what arduino gets.

Firefox uses favicons. I'm staring at two of them right now.

int x; //A number

        for(int x = 0; c != '/n' && x<22; x++) {

The two x variables are NOT the same. See why one letter global names are stupid?

      char Packet[client.available()];
      if (client.available()) {
        char c;
        for(int x = 0; c != '/n' && x<22; x++) {
          c = client.read();
          Packet[x] = c;
        }

Allocate some space. Then, keep reading and filling (and walking right past the end of that space) the array with crap until the terminator finally arrives. Stupid!

You are expecting a certain amount of data. Create an array that big NOT USING client.available() to define the size. Only read when there is data to read. DO NOT USE A FOR LOOP TO READ RANDOM AMOUNTS OF CRAP.

PaulS, have some coffee :slight_smile: The OP said the sample code doesn't make sense. So where does it not make sense? Right now your code is not making sense. If we know why you think a certain program makes no sense, we can find the root cause of your program not making sense.

liudr:
...
Firefox uses favicons. I'm staring at two of them right now.

sorry to go off-topic, but i don't see one now - well, i do see a gray generic globe, and it says "This website does not supply identity information."

Okay, but how will that affect the sending of data? I had it also print to the Serial console, and numbers showed up, not characters...that's what worries me...

Good/Bad News! My debugging script work, the request parsed perfectly. Here’s the serial output:
http://pastie.org/8810323
It’s wayyyyyyyyyyyyyyyyyyyyy too long to fit into a forum post, and the paste is about 1% of the 10000 lines of serial output.
What;s weird is that numbers were sent to the browser, and it didn’t realize. It kept sending HTTP requests.
Here’s my updated bezzaled code:

#include <SPI.h>     //The SPI Bus
#include <Ethernet.h>//Ethernet Chip stuff
#include <SD.h>      //SD Card
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Unique identifier that...I can pick!
IPAddress ip(192,168,1,130); //IP Adress that...I picked!
EthernetServer server(80); //It's important.
char current = 'x'; //Current Parsing Char //X is a placeholder
char FileName[8]; //You'll see

void setup()
{
  Serial.begin(57600); //Starts up the Serial at a baud rate of 9600
  Ethernet.begin(mac, ip); //Starts the Ethernet connection
  server.begin(); //Boot! //Begins the server
  SD.begin(4); //Start reading from that SD Card there
  pinMode(4, OUTPUT); //Important for SD sheild
  Serial.print("IP is at: "); //Prints that text
  Serial.println(ip); //Prints the IP
}
void loop() {
  EthernetClient client = server.available();
  if(client) { //Anyone Home?
    Serial.println("\nRequest Recieved!");
    while (client.connected()) {
      char Packet[22]; //<--21 long!
      if (client.available()) {
        char c = 'q'; //<-- q is a placeholder!
        for(int x = 0; c != '/n' && x<22; x++) { //The c != /n makes sure request is recieved
          c = client.read();
          Packet[x] = c;
          Serial.print("RequestChar: ");
          Serial.println(c);
        }
        if(Packet[0] == 'G' && Packet[1] == 'E' && Packet[2] == 'T') {
          for(int x=5; current != ' '; x++)
          {
            FileName[x-5] = Packet[x];
            current = Packet[x+1];
          }
        }
        Serial.println();
        Serial.println("File name is: ");
        Serial.println(FileName);
        if(FileName == " HTTP/1. ") {
          File myFile=SD.open("hom.htm");
          if(myFile) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");
            client.println("<!DOCTYPE HTML>");
            while(myFile.available()) {
              client.print(myFile.read());
            }
            myFile.close();
          }
        }
        File myFile=SD.open(FileName);
        if(myFile) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          while(myFile.available()) {
            client.print(myFile.read());
            Serial.print("ReplyChar: ");
            Serial.println(myFile.read());
           }
          myFile.close();
        }
        else {
          Serial.println("Oh Fiddlesticks!");
          Serial.println("Something is broken:");
          Serial.println();
          Serial.println();
          if(!SD.exists(FileName)) {
            Serial.println("Oops! It seems that that file doesn't exist!");
            Serial.println();
            Serial.println();
            client.println("HTTP/1.1 404 NOT FOUND");
            client.println("Connection: close");
          }
        }
      }
    }
  }
}

I don’t know why…isn’t there an option to convert ASCII numbers into strings? That would be pleasant.

i don't know if this is relevant but;

i copied the code snippet just for the for loop but got a response about the code itself, thought i'd just link it here for what it's worth.

waterlubber:
I don't know why...isn't there an option to convert ASCII numbers into strings? That would be pleasant.

I'm not sure what you're asking for here - a c-string is just a null-terminated array of ascii characters.

Your HTTP headers are malformed.
Try this

client.print("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n");
client.println("<!DOCTYPE HTML>");
//...etc...
 if (client.available()) {

        char c = client.read(); 
        if( c == '\n')
         ................... do whatever  

        for(int x = 0; c != '/n' && x<22; x++) { //The c != /n makes sure request is recieved
          c = client.read();
          Packet[x] = c;
          Serial.print("RequestChar: ");
          Serial.println(c);
        }

If you really , desperately, need to use unitialized ( what’s a placeholder? - same thing !) variable why not do something usefull and check for the terminating character BEFORE entering the for loop? It would be little safer.

But I really believe the usage of uninitialized stuff is a bad, bad, bad practice and probably brought up by “helpfull” compiler.

Your mileage and / or opinion may vary…

MattS-UK:
Your HTTP headers are malformed.
Try this

client.print("HTTP/1.0 200 OK\r\nContent-Type: text/html\r\nConnection: close\r\n\r\n");

client.println("");
//…etc…

Thanks a ton! You were right, FF now gets the reply…however, what it displays is weird. I am uploading an HTML document so you can see, clearly, the SD card is sending numbers instead of letters…quite odd.

WeirdResponse.htm (96 KB)

There is one file on a formatted, FAT32, 4GB MicroHCSD card. Here is the output of the Cardinfo sketch (http://arduino.cc/en/Tutorial/CardInfo)

Initializing SD card...Wiring is correct and a card is present.

Card type: SDHC

Volume type is FAT32

Volume size (bytes): 3644850176
Volume size (Kbytes): 3559424
Volume size (Mbytes): 3476

Files found on the card (name, date and size in bytes): 
HOM.HTM       2014-02-26 18:04:40 5573

Anyone have an idea why the myFile.read() is returning what looks to be ASCII numbers in decimal as opposed to characters themselves? It's quite weird. Do I need to use a function like str()? Is there an equivalent in arduino C++?

waterlubber:
Anyone have an idea why the myFile.read() is returning what looks to be ASCII numbers in decimal as opposed to characters themselves? It's quite weird. Do I need to use a function like str()? Is there an equivalent in arduino C++?

Use serial.write.