WiFi Client - No socket available even with client.flush(), client.stop()

Hi guys!

i’m using an arduino uno with wifi shield to switch a relay on and off (arduino gets the instructions from a server, to which i have access via a website).

no matter what i do, i keep getting the “No Socket Available” error, even though i flush() and stop() the client. everything else works fine, but after several runs of the loop i get the error mentioned above.

maybe somebody can help me. i’m posting the code i use below:

#include <Time.h>
#include <TimeAlarms.h>
#include <WiFi.h>
#include <WiFiUdp.h>


char ssid[] = "*********"; //  your network SSID (name) 
char pass[] = "********";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
IPAddress server(**,***,***,**);  

WiFiClient client;
int pin = 2;
int a;

void setup() {
  Serial.begin(9600);
  while(!Serial) {
  }
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present"); 
    while(true);
  } 

  while (status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000);
  } 
  pinMode(pin, OUTPUT);
}
//==================LOOP=======================
void loop() {
  //get command
  Serial.println("start loop");
  a = 0;
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  
  ConnectToClient(server, 80);
  //DisconnectClient();
  a = GetCommand();
  DisconnectClient();
  Serial.print("command: ");
  Serial.println(a);
  
  if (a!=0) {
    SwitchPinOn(a, pin);
    if(status!=WL_CONNECTED) {
      status = WiFi.begin(ssid, pass);
      delay(10000);
    }
    deleteit:
    Serial.println("delete it");
    DisconnectClient();
    DeleteCommand2(server, 80);
    delay(500);
    ConnectToClient(server, 80);
    //DisconnectClient();
    a = GetCommand();
    Serial.println(a);
    DisconnectClient();
    if (a!=0) goto deleteit;
  }
  Serial.println("done");
  Serial.println();
  delay(10000);
}
//=============================================

void ConnectToClient(IPAddress server,int port) {
  retry:
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  if (client.connect(server, port)) {
    Serial.println("ConnectToClient: connected to server");
    client.println("GET http://******.php HTTP/1.1");
    client.println("Host: ******");
    client.println("Connection: close");
    client.println();
    return;
  }
  else {
    Serial.println("ConnectToClient: try again");
    client.flush();
    client.stop();
    unsigned long timer = millis();
     while (millis() < timer + 5000) ;
    goto retry;  
  }
}

int GetCommand() {
  int pos;
  int command = -1;
  String httpReturn="";
  while (client.connected()) {
    while (client.available()) {
      char c = client.read();
      httpReturn += c;
    }
  }
  pos = httpReturn.indexOf("mins: ");
  command = httpReturn.substring(pos + 6, pos + 8).toInt();
  return command;
}

void DisconnectClient() {
  client.flush();
  client.stop(); 
  /*if (!client.connected()) {
    client.flush();
    client.stop();
  }
  else {
    client.flush();
    client.stop();
  }*/
  unsigned long timer = millis();
     while (millis() < timer + 5000) ;
  Serial.println("DisconnectClient: disconnected");
}

void DeleteCommand(IPAddress server,int port) {
  retry:
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  String postmsg = "minutes=0";
  if (client.connect(server, port)) {
    Serial.println("DeleteCommand: connected to server");
    //client.println("POST http://*******.php HTTP/1.1");
    client.println("POST /******.php HTTP/1.1");
    client.println("Host: **********");
    client.println("User-Agent: Arduino/1.0");    
    //client.println("Content-Type: application/x-www-form-urlencoded");    
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(postmsg.length());
    client.println();
    client.println(postmsg);  
    return;
  }
  else {
    Serial.println("DeleteCommand: try again");
    client.flush();
    client.stop();
    unsigned long timer = millis();
     while (millis() < timer + 5000) ;
    goto retry;  
  }
}

void DeleteCommand2(IPAddress server, int port) {
  retry:
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  
  if (client.connect(server, port)) {
    client.println("GET http://************.php HTTP/1.1");
    client.println("Host: **********");
    client.println("Connection: close");
    client.println();
    return;
  }
  else {
    client.flush();
    client.stop();
    unsigned long timer = millis();
     while (millis() < timer + 5000) ;
    goto retry;
  }
}


void SwitchPinOn(int in, int pin) {
  /*
  long minu = 60000;
  long dauer = (long) minu * in;
  digitalWrite(pin, HIGH);
  delay(dauer);
  digitalWrite(pin, LOW);
  */
  unsigned long minu = 60000;
  unsigned long dauer = (unsigned long) minu * in;
  unsigned long timer = millis();
  digitalWrite(pin, HIGH);
  while (millis() < timer + dauer) ;
  digitalWrite(pin, LOW);
}

This thread may answer your questions.

edit: client.flush() removes only the current packet characters from the socket. By the time you call client.stop(), the socket may already have characters from the next packet in it.

To dump all characters. use this:

while(client.connected()) {
  while(client.available()) client.flush();
}
client.stop();

thank you so much for your reply!

i included your suggestion into my code, but still i get the no socket available error.

when i run the code, the relay is usually switched on for 10-20 minutes.
it works for a while, but the error shows up after several cycles.
(i have marked the position in the code)

maybe you have another idea?

#include <Time.h>
#include <TimeAlarms.h>
#include <WiFi.h>
#include <WiFiUdp.h>


char ssid[] = "*******"; //  your network SSID (name) 
char pass[] = "*******";    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;            // your network key Index number (needed only for WEP)

int status = WL_IDLE_STATUS;
IPAddress server(*******);  

WiFiClient client;
int pin = 2;
int a;

void setup() {
  Serial.begin(9600);
  while(!Serial) {
  }
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present"); 
    while(true);
  } 

  while (status != WL_CONNECTED) { 
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000);
  } 
  pinMode(pin, OUTPUT);
}
//==================LOOP=======================
void loop() {
  //get command
  Serial.println("start loop");
  a = 0;
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  
  ConnectToClient(server, 80);
  //DisconnectClient();
  a = GetCommand();
  DisconnectClient();
  Serial.print("command: ");
  Serial.println(a);
  
  if (a!=0) {
    SwitchPinOn(a, pin);
    if(status!=WL_CONNECTED) {
      status = WiFi.begin(ssid, pass);
      delay(10000);
    }
    deleteit:
    Serial.println("delete it");
    //THE ERROR OCCURS IN THE NEXT LINE
    DeleteCommand2(server, 80);
    delay(500);
    ConnectToClient(server, 80);
    a = GetCommand();
    Serial.println(a);
    DisconnectClient();
    if (a!=0) goto deleteit;
  }
  Serial.println("done");
  Serial.println();
  delay(10000);
}
//=============================================

void ConnectToClient(IPAddress server,int port) {
  retry:
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  if (client.connect(server, port)) {
    Serial.println("ConnectToClient: connected to server");
    client.println("GET http://*******.php HTTP/1.1");
    client.println("Host: *******");
    client.println("Connection: close");
    client.println();
    return;
  }
  else {
    Serial.println("ConnectToClient: try again");
    while(client.connected()) {
      while(client.available()) client.flush();
    }
    unsigned long timer = millis();
     while (millis() < timer + 5000) ;
    client.stop();
    timer = millis();
    while (millis() < timer + 5000) ;
    goto retry;  
  }
}

int GetCommand() {
  int pos;
  int command = -1;
  String httpReturn="";
  while (client.connected()) {
    while (client.available()) {
      char c = client.read();
      httpReturn += c;
    }
  }
  pos = httpReturn.indexOf("mins: ");
  command = httpReturn.substring(pos + 6, pos + 8).toInt();
  return command;
}

void DisconnectClient() {
  while(client.connected()) {
   while(client.available()) client.flush();
  }
  unsigned long timer = millis();
     while (millis() < timer + 5000) ;
  client.stop(); 
  /*if (!client.connected()) {
    client.flush();
    client.stop();
  }
  else {
    client.flush();
    client.stop();
  }*/
  timer = millis();
     while (millis() < timer + 5000) ;
  Serial.println("DisconnectClient: disconnected");
}

/*void DeleteCommand(IPAddress server,int port) {
  retry:
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  String postmsg = "minutes=0";
  if (client.connect(server, port)) {
    Serial.println("DeleteCommand: connected to server");
    //client.println("POST http://*******.php HTTP/1.1");
    client.println("POST /*******.php HTTP/1.1");
    client.println("Host: *******");
    client.println("User-Agent: Arduino/1.0");    
    //client.println("Content-Type: application/x-www-form-urlencoded");    
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(postmsg.length());
    client.println();
    client.println(postmsg);  
    return;
  }
  else {
    Serial.println("DeleteCommand: try again");
    while(client.connected()) {
      while(client.available()) client.flush();
    }
    unsigned long timer = millis();
     while (millis() < timer + 5000) ;
    client.stop();
    timer = millis();
     while (millis() < timer + 5000) ;
    goto retry;  
  }
}*/

void DeleteCommand2(IPAddress server, int port) {
  retry:
  if(status!=WL_CONNECTED) {
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  
  if (client.connect(server, port)) {
    client.println("GET http://*******.php HTTP/1.1");
    client.println("Host: *******");
    client.println("Connection: close");
    client.println();
    return;
  }
  else {
    Serial.println("DeleteCommand: try again");
    while(client.connected()) {
      while(client.available()) client.flush();
    }
    unsigned long timer = millis();
     while (millis() < timer + 5000) ;
    client.stop();
    timer = millis();
     while (millis() < timer + 5000) ;
    goto retry;
  }
}


void SwitchPinOn(int in, int pin) {
  /*
  long minu = 60000;
  long dauer = (long) minu * in;
  digitalWrite(pin, HIGH);
  delay(dauer);
  digitalWrite(pin, LOW);
  */
  unsigned long minu = 60000;
  unsigned long dauer = (unsigned long) minu * in;
  unsigned long timer = millis();
  digitalWrite(pin, HIGH);
  while (millis() < timer + dauer) ;
  digitalWrite(pin, LOW);
}

maybe you have another idea?

Get rid of the twisted logic and all that goto crap. Then, we'll talk.

In addition to PaulS, if you get the message “no socket available”, you are not closing the connection properly.

edit: Here is my test code. It displays the socket status at each connection. One thing I did find is if the connection fails, your code must call client.stop, or the socket stays open (doesn’t close). Four fails and you get that “No socket available” message.

#include <WiFi.h>
#include <SPI.h>

// change to your server
IPAddress server(192,168,1,253);
char serverName[] = "192.168.1.253";

// change to your server's port
int serverPort = 80;

WiFiClient client;
char ssid[] = "MySSID";     // the name of your network
char pass[] = "mypassword";  // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status

int totalCount = 0;
int loopCount = 0;
char pageAdd[32];

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

  // disable SD SPI
  pinMode(4,OUTPUT);
  digitalWrite(4,HIGH);

  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println(F("WiFi shield not present")); 
    // don't continue:
    while(true);
  } 

  // check firmware version
  Serial.print(F("Firmware version: "));
  Serial.println(WiFi.firmwareVersion());
  
 // attempt to connect to Wifi network:
  while ( status != WL_CONNECTED) { 
    Serial.print(F("Attempting to connect to open SSID: "));
    Serial.println(ssid);
    status = WiFi.begin(ssid,pass);

    // wait 10 seconds for connection:
    delay(10000);
  }
   
  // you're connected now, so print out the data:
  Serial.print(F("You're connected to the network"));
  printCurrentNet();
  printWifiData();
  delay(2000);
  Serial.println(F("Ready"));
}

void loop()
{
  if(loopCount < 30)
  {
    // if loopCount is less than 30, just delay a second
    delay(1000);
  }
  else
  {
    // every thirty seconds this runs
    loopCount = 0;

    // Modify next line to load different page
    // or pass values to server
    strcpy(pageAdd,"/");

    // sprintf(pageAdd,"/arduino.php?test=%u",totalCount);

    if(!getPage(server,serverPort,pageAdd)) {
      Serial.print(F("Fail "));
    }
    else Serial.print(F("Pass "));

    totalCount++;
    Serial.println(totalCount,DEC);
  }    

  loopCount++;
}

byte getPage(IPAddress ipBuf,int thisPort, char *page)
{
  int inChar;
  char outBuf[128];

  ShowSockStatus();

  Serial.print(F("connecting..."));

  if(client.connect(ipBuf,thisPort))
  {
    Serial.println(F("connected"));

    ShowSockStatus();
    
    sprintf_P(outBuf,PSTR("GET %s HTTP/1.1\r\n"),page);
    client.write(outBuf);
    sprintf_P(outBuf,PSTR("Host: %s\r\nConnection: close\r\n\r\n"),serverName);
    client.write(outBuf);
  } 
  else
  {
    Serial.println(F("failed"));
    client.stop();
    return 0;
  }

  // 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();

  return 1;
}

void printCurrentNet() {
  // print the SSID of the network you're attached to:
  Serial.print(F("SSID: "));
  Serial.println(WiFi.SSID());

  // print the MAC address of the router you're attached to:
  byte bssid[6];
  WiFi.BSSID(bssid);    
  Serial.print(F("BSSID: "));
  Serial.print(bssid[5],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[4],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[3],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[2],HEX);
  Serial.print(F(":"));
  Serial.print(bssid[1],HEX);
  Serial.print(F(":"));
  Serial.println(bssid[0],HEX);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print(F("signal strength (RSSI):"));
  Serial.println(rssi);

  // print the encryption type:
  byte encryption = WiFi.encryptionType();
  Serial.print(F("Encryption Type:"));
  Serial.println(encryption,HEX);
}

void printWifiData() {
  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
    Serial.print(F("IP Address: "));
  Serial.println(ip);
  Serial.println(ip);
  
  // print your MAC address:
  byte mac[6];  
  WiFi.macAddress(mac);
  Serial.print(F("MAC address: "));
  Serial.print(mac[5],HEX);
  Serial.print(F(":"));
  Serial.print(mac[4],HEX);
  Serial.print(F(":"));
  Serial.print(mac[3],HEX);
  Serial.print(F(":"));
  Serial.print(mac[2],HEX);
  Serial.print(F(":"));
  Serial.print(mac[1],HEX);
  Serial.print(F(":"));
  Serial.println(mac[0],HEX);
  
  // print your subnet mask:
  IPAddress subnet = WiFi.subnetMask();
  Serial.print(F("NetMask: "));
  Serial.println(subnet);

  // print your gateway address:
  IPAddress gateway = WiFi.gatewayIP();
  Serial.print(F("Gateway: "));
  Serial.println(gateway);
}

void ShowSockStatus() {
  for(int x = 0; x < MAX_SOCK_NUM; x++) {
    Serial.print(F("Socket #"));
    Serial.print(x,DEC);
    if(WiFi._state[x] == -1) Serial.print(F(": available  port "));
    else Serial.print(F(": used  port "));

    Serial.println(WiFi._server_port[x]);    
  }
}

void SetSockStatus() {
  for(int x = 0; x < MAX_SOCK_NUM; x++) {
    WiFi._state[x] = -1;
  }
}

Hello,

I faced the same problem reported here and in similar posts like this one, marked as “solved”

indeed it’s not “solved”, as the solution proposed there didn’t worked for me (arduino 1.0.5 on debian, installed with apt)

I restructured the sample a little, changing its workflow, it seems to be working fine, at least compared to the original version or any proposed solutions or any other tweaks, like adding some delays.

I’m attaching a snapshot of arduino’s serial monitor (showing the new workflow) and the eclipse-tomcat console logger, which logs the HTTP requests from arduino (test data for the moment: I’m buiding a weather station with it).

cheers!
corrado