Well, for fast parsing I wouldn't use String for a start. I've written an example (below) which does away with the String class, and also demonstrates parsing the line once.
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
byte mac[] = { 0xB3, 0x8D, 0x72, 0x1D, 0xCE, 0x91 };
// Our IP address
IPAddress ip(10,0,0,241);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(115200);
while (!Serial) { } // wait for serial port to connect.
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print(F("Server is at "));
Serial.println(Ethernet.localIP());
} // end of setup
// how much serial data we expect before a newline
const unsigned int MAX_INPUT = 100;
// the maximum length of paramters we accept
const int MAX_PARAM = 10;
// Example GET line: GET /?foo=bar HTTP/1.1
void processGet (const char * data)
{
// find where the parameters start
const char * paramsPos = strchr (data, '?');
if (paramsPos == NULL)
return; // no parameters
// find the trailing space
const char * spacePos = strchr (paramsPos, ' ');
if (spacePos == NULL)
return; // no space found
// work out how long the parameters are
int paramLength = spacePos - paramsPos - 1;
// see if too long
if (paramLength >= MAX_PARAM)
return; // too long for us
// copy parameters into a buffer
char param [MAX_PARAM];
memcpy (param, paramsPos + 1, paramLength); // skip the "?"
param [paramLength] = 0; // null terminator
// do things depending on argument (GET parameters)
if (strcmp (param, "foo") == 0)
Serial.println (F("Activating foo"));
else if (strcmp (param, "bar") == 0)
Serial.println (F("Activating bar"));
} // end of processGet
// here to process incoming serial data after a terminator received
void processData (const char * data)
{
Serial.println (data);
if (strlen (data) < 4)
return;
if (memcmp (data, "GET ", 4) == 0)
processGet (&data [4]);
} // end of processData
bool processIncomingByte (const byte inByte)
{
static char input_line [MAX_INPUT];
static unsigned int input_pos = 0;
switch (inByte)
{
case '\n': // end of text
input_line [input_pos] = 0; // terminating null byte
if (input_pos == 0)
return true; // got blank line
// terminator reached! process input_line here ...
processData (input_line);
// reset buffer for next time
input_pos = 0;
break;
case '\r': // discard carriage return
break;
default:
// keep adding if not full ... allow for terminating null byte
if (input_pos < (MAX_INPUT - 1))
input_line [input_pos++] = inByte;
break;
} // end of switch
return false; // don't have a blank line yet
} // end of processIncomingByte
void loop()
{
// listen for incoming clients
EthernetClient client = server.available();
if (client)
{
Serial.println(F("Client connected"));
// an http request ends with a blank line
boolean done = false;
while (client.connected() && !done)
{
while (client.available () > 0 && !done)
done = processIncomingByte (client.read ());
} // end of while client connected
// send a standard http response header
client.println(F("HTTP/1.1 200 OK"));
client.println(F("Content-Type: text/html"));
client.println(F("Connection: close")); // close after completion of the response
client.println(); // end of HTTP header
client.println(F("<!DOCTYPE HTML>"));
client.println(F("<html>"));
client.println(F("<head>"));
client.println(F("<title>Test page</title>"));
client.println(F("</head>"));
client.println(F("<body>"));
client.println(F("<h1>My web page</h1>"));
client.println(F("<p>Requested actions performed"));
client.println(F("</body>"));
client.println(F("</html>"));
// give the web browser time to receive the data
delay(10);
// close the connection:
client.stop();
Serial.println(F("Client disconnected"));
} // end of got a new client
} // end of loop
The incoming lines from the client are captured in a static buffer. This eliminates issues with memory fragmentation (caused by using String).
processIncomingByte is called for each byte from the client. Once an entire line is assembled it calls processData. If that finds a "GET " line it calls processGet. That looks for the parameters on the GET line. The GET line looks like this:
GET /?bar HTTP/1.1
So we need to get between the "?" and the next space, to get the parameter ("bar" in this case). This can be accomplished by finding their positions with strchr.
Finally (as a simple example) I tested with strcmp for a direct match on various words. You could probably make that more efficient but I doubt it would matter much.
http://192.168.0.180?a1oorhttp://192.168.0.180?a1c, or might you have multiple of them on the GET line?