Solved: Ethernet client.connected() delay in response

For the solution scroll down :wink:

Hi Arduino makers!

I'm working with the Arduino for a month now, and I'm very enthousiast what this can bring in the realisation of out-of-the-box ideas. :smiley: In my vision, all the devices I'll create should be able to communicate with the internet to make them smarter.

So, I've started to create an Arduino JSON client example https://github.com/mikepage/Simple-Arduino-JSON-Client. It is based on the WebClient tutorial http://arduino.cc/en/Tutorial/WebClient.

I have noticed while running the code that in the code part

if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    for(;;)
      ;
  }

After printing the HTTP response and before the point

  if (!client.connected())

there is a 1 or 2 seconds delay, which is kind of long for using it with for example an NFC card reader. :wink:

A logical step to optimize my application speed is to parse the data directly in the client.available() loop. I have already did some testing with alternative methods like:

if (client.available() == 0) {

I would love to hear your thoughts on this issue.

I use this code with good results. It downloads Google homepage every 10 seconds.

Take a look at the getPage() function. It shows how to use the client.connected() and client.available() routines together to get all packets sent by the server.

Simple client test code you can try to see if it has the delay you notice.

//zoomkat 4-04-12
//simple client test
//for use with IDE 1.0
//open serial monitor and send an e to test
//for use with W5100 based ethernet shields
//note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605 
//the arduino lan IP address { 192, 168, 1, 102 } may need 
//to be modified modified to work with your router.

#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 assigned to arduino
//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 IP address
EthernetClient client;
//////////////////////

void setup(){

  Ethernet.begin(mac, ip);
  //Ethernet.begin(mac, ip, gateway, gateway, subnet);
  Serial.begin(9600); 
  Serial.println("Better client test 4/04/12"); // so I can keep track of what is loaded
  Serial.println("Send an e in serial monitor to test"); // what to do to test
}

void loop(){
  // check for serial input
  if (Serial.available() > 0) //if something in serial buffer
  {
    byte inChar; // sets inChar as a byte
    inChar = Serial.read(); //gets byte from buffer
    if(inChar == 'e') // checks to see byte is an e
    {
      sendGET(); // call sendGET function below when byte is an e
    }
  }  
} 

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

void sendGET() //client function to send/receive GET request data.
{
  if (client.connect(myserver, 80)) {  //starts client connection, checks for connection
    Serial.println("connected");
    client.println("GET /~shb/arduino.txt HTTP/1.0"); //download text
    client.println(); //end of get request
  } 
  else {
    Serial.println("connection failed"); //error message if no client connect
    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(); //gets byte from ethernet buffer
    Serial.print(c); //prints byte to serial monitor 
  }

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

}

I found out, after 24 hours of coding and testing, that the solution is actually very simple :smiley:

I found in the release note of Arduino 1.0.1 (21 May 2012) this:

The Serial class (as well as other classes inheriting from Stream, like
EthernetClient, SoftwareSerial, Wire and more) now contains functions
for parsing incoming data, based on the TextFinder library by Michael
Margolis. They include find() and findUntil() to search for data,
parseInt() and parseFloat() for converting incoming characters into
numeric values, and readBytes() and readBytesUntil() for reading
multiple bytes into a buffer.

...

They use a timeout that can be set with the new setTimeout().

I have added this function to my setup, and it works perfect!

void setup() {
  Serial.begin(9600);

  delay(1000);

  Ethernet.begin(mac);
  client.setTimeout(500);
  
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());
}

Thank you for all your help!

Kind regards,

Mike