Ethernet Shield Doesn't Close Socket After Client.Connect() Failure

After a failed client.connect() and issuing a client.stop() the socket remains open. With each additional failed client.connect another socket is left open until complete failure of communication. This program polls a controller every 3 seconds and displays the data on the serial port and shows socket status. For the first 40 minutes everything is fine, then a failure and socket left open. At 5 hours another failure occurs and total ethernet communication failure. Below is the code and excerpts from the serial log.

Any suggestions would be appreciated.

void loop()
{
//Serial Print Up time
Serial.print("Uptime: ");
Serial.print(millis() / 60000);
Serial.println(" Mins.");
Serial.println();

//Select IP address for the appropriate controller
int connectionStatus = client.connect(HouseController, 80);
Serial.println("Connecting To House Controller.");
Serial.println();

//Close connection if a connection failure occurs
if (connectionStatus < 1)
{
client.stop();
Serial.println("*************************************************");
Serial.println("Stopping Client after initial connection failure.");
}

//Show Socket Status On Serial Monitor
ShowSockStatus();

//If connection successful to controller request JSON Data
if (connectionStatus == 1)
{
// Make a HTTP request:
client.println("GET /status.json HTTP/1.1");
client.println("Connection: close");
client.println();
}

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

Serial.println();
Serial.println();
//Flush Remaining Data In Ethernet Controller
client.flush(); //Clear Data Buffer In Ethernet Controller
client.stop(); //Close Communication With Irrigation Controller

delay(3000);
}

void ShowSockStatus()
{
Serial.println();
for (int i = 0; i < MAX_SOCK_NUM; i++) {
Serial.print(F("Socket#"));
Serial.print(i);
uint8_t s = W5100.readSnSR(i);
socketStat = s;

  • Serial.print(F(":0x"));*
  • Serial.print(s,16);*
  • Serial.print(F(" "));*
  • Serial.print(W5100.readSnPORT(i));*
  • Serial.print(F(" D:"));*
  • uint8_t dip[4];*
  • W5100.readSnDIPR(i, dip);*
  • for (int j=0; j<4; j++) {*
  • Serial.print(dip[j],10);*
  • if (j<3) Serial.print(".");*
  • }*
  • Serial.print(F("("));*
  • Serial.print(W5100.readSnDPORT(i));*
  • Serial.println(F(")"));*
    }
  • Serial.println();*
    }
    Connecting To House Controller.
    *************************************************
    Stopping Client after initial connection failure.
    Socket#0:0x14 80 D:0.0.0.0(0)
    Socket#1:0x15 1814 D:192.168.0.102(80)
    Socket#2:0x0 0 D:0.0.0.0(0)
    Socket#3:0x0 0 D:0.0.0.0(0)
    Uptime: 41 Mins.
    Connecting To House Controller.
    Socket#0:0x14 80 D:0.0.0.0(0)
    Socket#1:0x17 1814 D:192.168.0.102(80)
    Socket#2:0x17 1815 D:192.168.0.102(80)
    Socket#3:0x0 0 D:0.0.0.0(0)
    Connecting To House Controller.
    *************************************************
    Stopping Client after initial connection failure.
    Socket#0:0x14 80 D:0.0.0.0(0)
    Socket#1:0x17 1814 D:192.168.0.102(80)
    Socket#2:0x15 6746 D:192.168.0.102(80)
    Socket#3:0x0 0 D:0.0.0.0(0)
    Uptime: 302 Mins.
    Connecting To House Controller.
    *************************************************
    Stopping Client after initial connection failure.
    Socket#0:0x14 80 D:0.0.0.0(0)
    Socket#1:0x17 1814 D:192.168.0.102(80)
    Socket#2:0x17 6746 D:192.168.0.102(80)
    Socket#3:0x0 6747 D:192.168.0.102(80)
    Uptime: 303 Mins.
    Connecting To House Controller.
    *************************************************
    Stopping Client after initial connection failure.
    Socket#0:0x14 80 D:0.0.0.0(0)
    Socket#1:0x17 1814 D:192.168.0.102(80)
    Socket#2:0x17 6746 D:192.168.0.102(80)
    Socket#3:0x0 6748 D:192.168.0.102(80)

Use code tag for the posting your code

Can you post your compete code with setup(); I wanted to see all, since it missng above code. Configuration is very importatant here.

Please check configuration setting else manually align the IP address

Here's a copy of the complete code. I have been working with this problem for quite awhile with no success. I wrote this little bit of code to prove something was wrong with the ethernet hardware / software. I have tried using other controllers and arduinos with the same result.

Thanks for any assistance.

Client_Stop_Test.ino (3.5 KB)

What kind of device has the IP 192.168.0.102? It seems that is the device locking up your sockets.

The unit is called "Irrigation Caddy". Here's the web page:

http://www.irrigationcaddydirect.com

I have up to 3 of them I wish to gather data from. The http page I request contains JSON (JavaScript Object Notation) data. Here's a sample of what it provides:

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Cache-Control: no-cache

{"zoneNumber":0,"progNumber":0,"allowRun":true,"running":false,"useSensor1":false,"isRaining":true,"zoneSecLeft":0,"progSecLeft":0,"maxZones":10}

I need a way to force the socket(s) closed since this controller will run 24hours a day.

prlindstrom:
After a failed client.connect() and issuing a client.stop() the socket remains open.

Stopping Client after initial connection failure.
Socket#0:0x14 80 D:0.0.0.0(0) // 0x14 = Listening socket
Socket#1:0x17 1814 D:192.168.0.102(80)
Socket#2:0x17 6746 D:192.168.0.102(80)
Socket#3:0x0 6748 D:192.168.0.102(80)

It looks like your sockets are being used up with successful connections (0x17 = ESTABLISHED). The sockets marked with 0x0 are CLOSED. The ones marked 0x15 are SYNSENT (trying to open). One socket is in status 0x14: LISTENING.

The server closes the connection. If your server is not closing the connection, you need to timeout the connection on the client end. Here is what I use on the client to timeout a broken connection or stalled server.

  // connectLoop controls the hardware fail timeout
  int connectLoop = 0;

  while(client.connected())
  {
    while(client.available())
    {
      inChar = client.read();
      Serial.write(inChar);
      // set connectLoop to zero if a packet arrives
      connectLoop = 0;
    }

    connectLoop++;

    // if more than 10000 milliseconds since the last packet
    if(connectLoop > 10000)
    {
      // then close the connection from this end.
      Serial.println();
      Serial.println(F("Timeout"));
      client.stop();
    }
    // this is a delay for the connectLoop timing
    delay(1);
  }

  Serial.println();

  Serial.println(F("disconnecting."));
  // close client end
  client.stop();

The full code I use is here.
http://playground.arduino.cc/Code/WebClient

edit: You didn't answer my main question. What kind of device is 192.168.0.102? LAMP server? Windows? Arduino?

The Product is called "Irrigation Caddy" the link to the website is in my previous post. I do not know what type of controller / operating system used within the product. My guess it is a custom built hardware / software design. I will add another client.stop() with a time delay and report back tomorrow.

Thanks for the assistance.

Did you try my client code I posted on the playground? The link to it is in reply #6 above.

edit: If you really need to force the sockets closed, I use this with my server code. I call it every iteration of loop. It closes any open sockets if they have been open more than 30 seconds.

#include <utility/w5100.h>
#include <utility/socket.h>

unsigned long connectTime[MAX_SOCK_NUM];
byte socketStat[MAX_SOCK_NUM];

void checkSockStatus()
{
  unsigned long thisTime = millis();

  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    uint8_t s = W5100.readSnSR(i);

    if((s == 0x17) || (s == 0x1C)) {
        if(thisTime - connectTime[i] > 30000UL) {
          Serial.print(F("\r\nSocket frozen: "));
          Serial.println(i);
          close(i);
        }
    }
    else connectTime[i] = thisTime;

    socketStat[i] = W5100.readSnSR(i);
  }
}

I incorporated the code which includes the timeout feature as requested in post #6 (see attached code). This did not change the result. At 72 minutes from the start I had two open connections for 192.168.0.102 controller and another at 111 minutes. See the serial log below:

Uptime: 72 Mins.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x15 2401 D:192.168.0.102(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Uptime: 72 Mins.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 2401 D:192.168.0.102(80)
Socket#2:0x17 2402 D:192.168.0.102(80)
Socket#3:0x0 0 D:0.0.0.0(0)

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Cache-Control: no-cache

{"zoneNumber":0,"progNumber":0,"allowRun":true,"running":false,"useSensor1":false,"isRaining":true,"zoneSecLeft":0,"progSecLeft":0,"maxZones":10}

Uptime: 111 Mins.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 2401 D:192.168.0.102(80)
Socket#2:0x17 3137 D:192.168.0.102(80)
Socket#3:0x0 0 D:0.0.0.0(0)

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Cache-Control: no-cache

{"zoneNumber":0,"progNumber":0,"allowRun":true,"running":false,"useSensor1":false,"isRaining":true,"zoneSecLeft":0,"progSecLeft":0,"maxZones":10}

Uptime: 111 Mins.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 2401 D:192.168.0.102(80)
Socket#2:0x15 3138 D:192.168.0.102(80)
Socket#3:0x0 0 D:0.0.0.0(0)

Uptime: 111 Mins.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 2401 D:192.168.0.102(80)
Socket#2:0x17 3138 D:192.168.0.102(80)
Socket#3:0x0 3139 D:192.168.0.102(80)

Client_Stop_Test_With_Socket_Status.ino (3.88 KB)

I attempted to incorporate the socket closing function, but without success (code attached). It startups fine, but 30 seconds later it states the socket is frozen and no data is being received from the irrigation controller. (see serial log below). I you can tell me what I have do wrong it would be appreciated.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1041 D:192.168.0.102(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Cache-Control: no-cache

{"zoneNumber":0,"progNumber":0,"allowRun":true,"running":false,"useSensor1":false,"isRaining":true,"zoneSecLeft":0,"progSecLeft":0,"maxZones":10}

Connecting To Coral Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1042 D:192.168.0.104(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Cache-Control: no-cache

{"zoneNumber":0,"progNumber":0,"allowRun":true,"running":false,"useSensor1":false,"isRaining":true,"zoneSecLeft":0,"progSecLeft":0,"maxZones":10}

Uptime: 0 Mins.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1043 D:192.168.0.102(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Socket frozen: 1

Connecting To Coral Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1044 D:192.168.0.104(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Socket frozen: 1

Client_Stop_Test_With_Socket_Close.ino (4.36 KB)

There is a problem there somewhere. If the server doesn't close the connection within 10 seconds of sending the last packet, the serial monitor would show a "Timeout", but I don't see that. If the server didn't close the connection, it wouldn't exit the "while(client.connected())" loop until the loop times out.

Add some more serial output to your code. I added two three lines to your code. Look for "// add this" in the code below. (edit: You forgot to reset connectLoop in your code)

 for( int i=1; i<3; i++ )
  {
    if(i==1)
    {

      //Select IP address for the appropriate controller
      connectionStatus = client.connect(HouseController, 80);
      Serial.println("Connecting To House Controller.");
      Serial.println();
    }
    else
    {
      connectionStatus = client.connect(CoralController, 80);
      Serial.println("Connecting To Coral Controller.");
      Serial.println();
    }

    //Show Socket Status On Serial Monitor
    ShowSockStatus();  

    //Close Sockets Open Greater Than 30 Seconds
    checkSockStatus();  

    //If connection successful to controller request JSON Data
    if (connectionStatus == 1) 
    {

// add this
      Serial.println("Connection success. Sending request");

      // Make a HTTP request:
      client.println("GET /status.json HTTP/1.1");
      client.println("Connection: close");
      client.println();
    } 

// add this 
   connectLoop = 0;

    while(client.connected())
    {
      while(client.available())
      {
        inChar = client.read();
        Serial.write(inChar);
        // set connectLoop to zero if a packet arrives
        connectLoop = 0;
      }

      connectLoop++;

      // if more than 10000 milliseconds since the last packet
      if(connectLoop > 10000)
      {
        // then close the connection from this end.
        Serial.println();
        Serial.println(F("Timeout"));
        client.stop();
      }
      // this is a delay for the connectLoop timing
      delay(1);
    }

    Serial.println();
    Serial.println();
    //Flush Remaining Data In Ethernet Controller
    client.stop();  //Close Communication With Irrigation Controller

// add this
    Serial.println("Disconnected");
  }

edit: Maybe you are sending the requests too often?

I added the serial comment lines as requested (see the attached code) and increased the delay from 3 to 10 seconds for the main loop. It still freezes at 30 seconds. Below is the serial log:

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1029 D:192.168.0.102(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Connection success. Sending request
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Cache-Control: no-cache

{"zoneNumber":0,"progNumber":0,"allowRun":true,"running":false,"useSensor1":false,"isRaining":true,"zoneSecLeft":0,"progSecLeft":0,"maxZones":10}

Disconnected
Connecting To Coral Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1030 D:192.168.0.104(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Connection success. Sending request
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Cache-Control: no-cache

{"zoneNumber":0,"progNumber":0,"allowRun":true,"running":false,"useSensor1":false,"isRaining":true,"zoneSecLeft":0,"progSecLeft":0,"maxZones":10}

Disconnected
Uptime: 0 Mins.

Connecting To House Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1031 D:192.168.0.102(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Socket frozen: 1
Connection success. Sending request

Disconnected
Connecting To Coral Controller.

Socket#0:0x14 80 D:0.0.0.0(0)
Socket#1:0x17 1032 D:192.168.0.104(80)
Socket#2:0x0 0 D:0.0.0.0(0)
Socket#3:0x0 0 D:0.0.0.0(0)

Socket frozen: 1
Connection success. Sending request

Disconnected

Client_Stop_Test_With_Socket_Close.ino (4.48 KB)

Have you tried my client code with just one of the servers?
http://playground.arduino.cc/Code/WebClient

The problem with your code is you try to get a response from a "connection" and close the "connection" that occasionally isn't connected.

I would start with tested code like mine above. The code above is easy to adapt to connections to multiple servers, but do that after you test both servers individually.

I'm having the same issue, a server is running and a client running 24/7 without issues, but after a while the client that should report some status to a webserver stops working.

apparently gets connected to the remote server but is not transmitting, this night I will try to increase the timeout/retry options

SurferTim: "The problem with your code is you try to get a response from a "connection" and close the "connection" that occasionally isn't connected."

may I ask why this would be a problem? I have a default client.close() at the end of my loops, would this be an issue?

thanks!

amigos me puede ayudar con la funcion para cerrar los socket en 0x17 y 0x1c de SurferTim me sale error en close
gracias