WiFi Shield doesn't close connection with client.stop()

Hi everyone ,

I'm using the official Arduino WiFi Shield to act as a client with my computer.

If necessary I'll upload the whole code , but it's kinda long and most of it is unnecessary since it basically works like this :
-Connect to the WiFi network , then to the computer's IP to a specified port (eg 10010)
-Send some stuff , don't wait for the response
-Disconnect (release the socket) with client.stop().

I'm testing the behaviour with a port listener(RLJ's) and all runs well except for the last part of the content to be sent,and the disconnection ;basically if I look up the port listener incoming data , it'll show:

Client connected
almost everything that's supposed to be sent

and that's it. The only way to receive that last part of the content , and to show a "Client disconnected " on the port listener's console , is to either :

-Restart the arduino without powering it off , and in this way it'll deliver that last message part and will be detected as disconnected and connected again right after

-Connect the computer to a different network while the arduino's still on , and it'll behave the same way , minus the reconnecting part.

Powering off the Arduino won't cause the above behaviours. Also it behaves in the exact same way with the WiFi client example , meaning that connecting the arduino to google itself goes smooth, but using the port listener to see what the arduino is sending still won't display the "Client disconnected" at the end.

So, do you think that it's using a port listener that's wrong because it isn't a "real" server , or is it a problem with the shield itself, or with my code ?

Thanks y'all.

You really should post your code.

If the sketch is client code, you may have trouble with closing the connection if you do not read the response from the server. Normally, a socket will not close if there is data in the buffer. Is there a reason you do not read the response? You don't need to do anything with it, just empty the rx buffer.

Hi Tim thanks for your quick reply, yes I'll post the code ASAP! Meanwhile, do you think a simple client.flush() could do the trick then?

OK so here’s the code , it’s quite lengthy and most of it doesn’t really operate a lot through the WiFiClient ; those operations that require wireless communication are performed by a WiFiClient contained into the “KP” object , so everytime there’s a _comm.[] ,those are wireless operations.

It actually all boils down to the client connecting , sending some stuff ,not caring about received data and then closing the connection.

I also tried adding a client.flush() (both in this code and in the Client example) ,but it won’t budge all the same.

I hope the code’s the least understandable , if not I’ll repost adding some comments in it.

byte KP::composeMessage(char code, Triple t) {

  if (!initializeSD()) return SD_ERR_INI;

  File xtemp;
  char name[5] = "";
  name[0] = code;

  strcat(name, "temp");
  #ifdef DEBUG
  Serial.println(name);
  #endif

  xtemp = SD.open(name, FILE_READ);
  _comm.connect(_ip, _port);
  if (xtemp) {

    #ifdef DEBUG
    Serial.println(F("File successfully opened"));
    #endif

    char c, cState = 'i'; //first part of the contents chain will always be the transaction id
    char state, lastState ; // used by the sequence reader

    char tagName[MAX_NAME_SIZE] = {""}, buffer[MAX_PACKET_SIZE] = {""};

    byte i = 0, count = 0; //i : needed for knowing the length of buffered tag name

    bool readingName = false, last = true;

    Contents curr = create(code, &cState, t);

    while (xtemp.available() > 0) {

      c = xtemp.read();
      state = c;
      buffer[count++] = c;
      Serial.print(c);

      if (count > MAX_PACKET_SIZE - 2 || xtemp.peek() <= 0) {
        _comm.write(buffer);
        strncpy(buffer, "", sizeof(buffer));
        count = 0;
        delay(TX_LATENCY);
      }


      if (cState != 'z') { //z means no more content to be added

        if (lastState == '<' && state != '/' ) { //that is , a tag has been opened but it's not a closing one

          readingName = true;
          #ifdef DEBUG
          Serial.println(F("Tag opened "));
          #endif
        }

        if (state == '>') {

          if (readingName) { //finished reading tagName

            #ifdef DEBUG
            Serial.print(F("Found tag: -"));
            Serial.print(tagName);
            Serial.print(F("- Searching for: -"));
            Serial.print(curr.type);
            Serial.println("-");
            #endif

            if (strncmp(tagName, curr.type, i) == 0) {

              #ifdef DEBUG
              Serial.println(F("Found content!: "));
              Serial.println(tagName);
              #endif

              if (count > 0 && count + strlen(curr.content) > MAX_PACKET_SIZE - 2) {
                _comm.write(buffer);
                count = 0;
                strncpy(buffer, "", sizeof(buffer));
                delay(TX_LATENCY);
              }

              strcat(buffer, curr.content);
              count += strlen(curr.content);
              curr = create(code, &cState, t);

            }

            strncpy(tagName, "", sizeof(tagName));
            i = 0;
          }
          readingName = false;
        }

      }

      if (readingName) tagName[i++] = c;

      lastState = state;
    }

    _comm.stop();
    xtemp.close();


    return OK;
  }


  #ifdef DEBUG
  Serial.print(F("Error File: "));
  Serial.println(code);
  #endif

  return SD_ERR_FILE;
}

Do I think client.flush will do the same thing as reading until the server closes the connection? No.

Ok,so maybe the problem is that I'm not using a real server application but rather just a port listener that doesn't automatically close the connection?

I've actually tried reading the data that the listener sends back,as you suggested, (it'll always reply "Hello!" to any newly connected client), in the Client example, both with and without flushing the buffer after, and it'll always hold the same result: the client won't disconnect unless it's trying to reconnect from scratch.

I'm also wondering why with the code I posted, the last part of the data that should be sent will be delivered and shown in the listener console ONLY upon disconnection of the client (caused by it trying to reconnect from scratch)..

You could try something like this.

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

client.stop();

It still isn't working.. I'm really starting to believe it's the listener's fault rather than Arduino's,so I'm gonna try and use a 'real' server application and see how it comes out, and then I'll report back here. Anyhow thanks for the help!

I thought the Arduino was a client?

I'm using the official Arduino WiFi Shield to act as a client with my computer.

What are you using as a server now?

Dadu:
It still isn't working.. I'm really starting to believe it's the listener's fault rather than Arduino's,so I'm gonna try and use a 'real' server application and see how it comes out, and then I'll report back here. Anyhow thanks for the help!

Yes,the Arduino is always acting as a client.

In these two days I've been only using RLJ's Port Listener to monitor the data transmission through the port to which the Arduino was connecting to.

Now I'll be using a server application written in java (not by me) that receives XML messages sent by registered clients and reply back with infos, errors,etc..

In the first tries this application wouldn't even reply to consecutive messages unless the Arduino first disconnected between a message and the next, so the reason I was using only the port listener for the time being was to analyse how the Arduino connected and disconnected to the pc (where the application's hosted)

If you are talking about standard client/server comm between two devices, the client sends a request to the server, then the server sends response packets to the client until it is finished, then closes the connection on its end. Then the client closes the connection on its end. If your “server” is not sending a close packet, the client will not be able to tell when the server is finished sending packets.

Ok so I've done some experiments and this is what came out of it:

This is the behaviour of my code as seen on server's side : you can see how the Arduino disconnected first , and that's because it was already connected before being reset, and how it reconnects , sends the message and doesn't disconnect again ,even if using client.stop() (it behaves exactly the same when using your solution with client.flush(),unfortunately). The exact same events take place when using the WiFi Client : it doesn't disconnect at the end.

This , however , it's how another client application (running on the same computer , accessing the port through localhost) behaves , and, message content apart, you can see how it's able to disconnect right after having sent the message and then having read the server's response ; my guess it's that the connection closes on client side first because that listener keep connections open indefinitely.

I've found @ this link some insights regarding the official WiFi Shield , most notoriously :

WiFiClient.Stop() does not close the connection by signalling the target host but rather, abandons the socket structure and any data associated with it. Calling WiFiClient.Stop() after writing to the Shield but before the transmit request is serviced, 2 seconds later, will cause the data to be abandoned. In any case, calling WiFiClient.stop() will leave the target with a dead peer connection.

The easiest solution in order to be sure of having closed the connection , in my case, would be to cycle through all 4 sockets with 4 consecutive client.connect() calls to the same port , but I don't think this would be ideal , especially considering that later on I'll need to reserve a pair of socket for stable connections and ,from what I understand , cycling through the sockets would mean those connections would be lost , right?

I gave up on the original wifi shield. It was way too unreliable. I have not tried the new wifi shield, so I don't know about any bugs it might have.