So I have found the code for a Arduino web server here on the forums that allows images and CSS files to be supplied to the client on request but I do not understand some parts of the code. I have been looking through this whole forum for tips how to program this myself but most of the popular codes didn't work for me.
This is the code that I found and is working flawlessly.
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
// MAC address from Ethernet shield sticker under board
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0xE7, 0xAC };
IPAddress ip(192, 168, 1, 20); // IP address, may need to change depending on network
EthernetServer server(80); // create a server at port 80
File webFile;
char header[80];
char filename[80];
int txtlen;
uint8_t buf[64];
int aantal;
void setup()
{
pinMode(53, OUTPUT);
Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
Serial.begin(9600); // for debugging
// initialize SD card
Serial.println("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("ERROR - SD card initialization failed!");
return; // init failed
}
Serial.println("SUCCESS - SD card initialized.");
}
void loop()
{
EthernetClient client = server.available(); // try to get client
txtlen = 0;
if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
if (txtlen < 79) {
header[txtlen++] = c;
header[txtlen] = 0;
}
// last line of client request is blank and ends with \n
// respond to client only after last line received
Serial.write(c);
if (c == '\n' && currentLineIsBlank) {
ExtractFileName();
Serial.print("Extracted filename is: ");
Serial.println(filename);
webFile = SD.open(filename); // open web file
if (!webFile) {
Serial.println("File not found!!");
client.println("HTTP/1.1 404 NOT FOUND");
}
else {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
}
client.println("Connection: close");
client.println();
// send web page
if (webFile) {
while(aantal = webFile.available()) {
if (aantal > 64) {
webFile.read(buf, 64);
client.write(buf, 64);
}
else {
webFile.read(buf, aantal);
client.write(buf, aantal); // send web page to client
}
}
webFile.close();
}
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(100); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
void ExtractFileName()
{
int i, j;
i=0;
while (header[i++] != ' ') {
;
}
j=0;
while (header[i] != ' ') {
filename[j++] = header[i++];
}
filename[j] = 0;
if (filename[0] == '/' && filename[1] == 0) {
strcpy(filename, "index.htm");
}
}
The author of the code posted it as a reply in a topic with a similar issue I had but he didn't post this code anywhere else and it isn't commented enough for me to understand why he programed some things the way he did. The main confusing parts are the "int aantal;" variable. I am not sure what the point of that variable is, and I don't understand how his function ExtractFileName works. I understand the rest of the code more or less, its just that I don't understand the logic behind some of the code as I am working with HTTP requests for the first time.
That looks like zoomkat's code, or someone copying his code. The purpose of the 64 byte sends is to increase the speed of the send. If you send the response in 64 byte packets rather than 1 byte packets, you get a 4x speed increase.
So the aantal variable i just there to check if the file is bigger than 64 bytes? And if it is it sends it in 64 byte chunks, else it just sends it as big as it is (63 bytes or less)?
Did you guys understand the ExtractFileName function?
void ExtractFileName()
{
int i, j;
i=0;
while (header[i++] != ' ') {
;
}
j=0;
while (header[i] != ' ') {
filename[j++] = header[i++];
}
filename[j] = 0;
if (filename[0] == '/' && filename[1] == 0) {
strcpy(filename, "index.htm");
}
}
I don't understand why he is using 2 counters here and what his output is supposed to be. Is this just a way of copy pasting a word letter by letter or what?
I'm surprised zoomkat hasn't jumped in here yet, but I would do a forum search for zoomkat's server code with the SD file stuff. He does that correct and it is fast.
I was trying to find some of zoomkat's webserver sketches but the search is very hard to use to get useful things back. I seen 1 sketch but it had servo variables that I don't need, maybe I cut out too much code from it because it didn't work for me, I tried going through his profile but he got over 7k posts so its hard to find the exact posts where he posted the webserver with SD card support.
Ill try some of his code that I did find around other people's posts and see how it turns out because I need a code that I can easily understand and this code I found is a bit too complicated for me. Id rather have a simple code that I can learn how to tweak, than a complicated one that I am afraid to touch not to break things.
Thank you very much guys, and if you have any useful SD card webserver links (zoomkats maybe) be sure to link them as I have been failing in finding them.
I got another question related to my Arduino Web Server.
Is it possible to connect to the Arudino via DNS? Like set it up so that my Arduino has a address like "www.example.com" or some other way. I only managed to find ways for the Arduino to connect to websites via DNS but no examples for a client connecting to the Arduino using a URL instead of the IP address its given.
I only managed to find ways for the Arduino to connect to websites via DNS but no examples for a client connecting to the Arduino using a URL instead of the IP address its given.
The Arduino is a web server, not a domain server. In order to address it by name, you need to get all the DNS servers in the world to know the name and IP address. That is typically done by buying a domain, and registering the IP address that hosts that domain.
Unless the Arduino has a static IP address, not just a local IP address, you won't be able to register its IP address.