TCP server does not recognise client close and freeze

Hello,

I have the following problem:
If the photon does not recognise that the client is disconnected (eg. I move out of the routers rage with the client, or I put it on flight mode (it is an ipad) the free memory starts to decrease and the photon freeze.

#include "application.h"

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);
TCPServer server = TCPServer(3456);

TCPClient client;
byte tcp_msg[1152] = {0};
unsigned long last_millis = 0;

boolean connected_to_me = false;

void setup() {
    WiFi.connect();
    Serial.begin(115200);
    server.begin();
}

void loop() {


  
    if (client.connected()) {
        unsigned long start_millis = millis();
        while (client.available()) {
            Serial.write(client.read());
        }
    } else {
        if (connected_to_me) {
            Serial.println("Disconneted from server");
            client.stop();
            connected_to_me = false;
        }
        client = server.available();
        if(client) {
            connected_to_me = true;
            Serial.println("client connected");
        }
        
    }
    
 
    
    if (millis() - last_millis >= 100) {
        unsigned long current_millis = millis();
        Serial.printf("%lu\t%i\t%lu\n", current_millis, connected_to_me, System.freeMemory());
        last_millis = current_millis;
        int count = client.write(tcp_msg, 1152);
        if (count == -16) {
            Serial.println("buffer is full");
        }
                
                
    }

}```

How can I solve this? 

Thank you very much!

I could make a workaround!
I have noticed that the memory decreases always by 1264 bytes every 100 ms.
So I just monitor and if it three time in a row decreases I just close the tcp connection…
However would be nice if somebody could tell a real solution.

long last_free_memory = 0;
int free_memory_error = 0;

and in the loop:

        long current_free_memory = System.freeMemory();
        long diff_free_memory = last_free_memory - current_free_memory;
        if (diff_free_memory == 1264) {
            free_memory_error++;
            if (free_memory_error == 3) {
                Serial.println("bug found");
                client.stop();
               connected_to_me = false;
                free_memory_error = 0;
            }
        } else {
            free_memory_error = 0;
        }
1 Like

You are doing some checks to see if the client is connected, but in the millis timer section, you do not ever check to see if the client is connected. But you still do client.write() every 100ms. It would seem that you should not indiscriminately publish to the client if you know it is disconnected.

You could add an extra check in the millis timer section to verify that client.connected() == true. Or you could add a return; statement to your conditional check for if (client.connected()) if the client is not connected.

Thanks for input!
Sorry you are right! But please note I have shorten my original code to make it simple and illustrate the problem. If I check before client.write(tcp_msg, 1152); it has the same result, because the client.connected() return true even if the client is disconnected (in not a normal way, eg. you move out with your client from the wifi range)… As you can see on my screenshot, the free memory is 44320 with client connected. at 90001ms the client disconnected, but the system still show it is connected… and at the same time the memory decreases in the next 500 ms by 1264 bytes every 100ms and then freeze…

There are situations where the client becomes disconnected and TCPServer won’t know that it happened. Basically the TCP connection will keep buffering data assuming that the packets are just getting lost and retrying them.

This is partially a limitation of TCP, because it doesn’t know for sure when the network has really gone away, or is just temporarily not responding.

In protocols where there’s an acknowledgement, you can tell from that. Including a timeout is also a good idea, in case you get no data from the other side.

Also, I’m pretty sure the -16 buffer full error only occurs on 0.6.x. The behavior is different in 0.7.0 and 0.8.0-rc.

3 Likes

Thanks for the info!

Yes, I thought so that is the problem.
I have also tried with settimeout but no luck, because I have 500ms to detect the problem.
However monitoring the memory and closing the connection if I see continuous decrease solved the problem for now.

1 Like

With the latest firmware fortunately I do not have to use the workaround because the -16 buffer full error seems to work, and I can close the connection after 3 seconds. However by closing the connection the memory does not free up. And if the device is connected again, and then if there is a disconnection again then we run out of the memory, and get a -8 error for the getwriteerror.
After a sec the memory frees up… but only if there is a new connection, and the time also can be 5-60 seconds…

I send 1152 bytes every 100 ms…

How can I free up the memory?

if  client.connected is true the columns are:
millis(), System.freeMemory(), client.getWriteError(), client.write(tcp_msg, 1152, 0);
if  client.connected is false the columns are:
millis(), System.freeMemory()

172455 15216
172555 15216
172593 connected ipad
172656 14576  0 1152
172756 14576  0 1152
172856 14576  0 1152
172956 14576  0 1152
173056 14576  0 1152
173156 14576  0 1152
173256 14576  0 1152
173356 14576  0 1152
173456 14576  0 1152
173556 14576  0 1152
173656 13312  0 1152
173756 14576  0 1152
173856 14576  0 1152
173956 14576  0 1152
174056 14576  0 1152
174156 14576  0 1152
174256 14576  0 1152
174356 14576  0 1152
174456 14576  0 1152
174556 14576  0 1152
174656 13312  0 1152
174756 12048  0 1152
174856 10784  0 1152
174956 9520  0 1152
175056 8256  0 1152
175156 6992  -16 -16
175256 6992  -16 -16
175356 6992  -16 -16
175456 6992  -16 -16
175556 6992  -16 -16
175656 6992  -16 -16
175756 6992  -16 -16
175856 6992  -16 -16
175956 6992  -16 -16
176056 6992  -16 -16
176156 6992  -16 -16
176256 6992  -16 -16
176356 6992  -16 -16
176456 6992  -16 -16
176556 6992  -16 -16
176656 6992  -16 -16
176756 6992  -16 -16
176856 6992  -16 -16
176956 6992  -16 -16
177056 6992  -16 -16
177156 6992  -16 -16
177256 6992  -16 -16
177356 6992  -16 -16
177456 6992  -16 -16
177556 6992  -16 -16
177656 6992  -16 -16
177756 6992  -16 -16
177856 6992  -16 -16
177956 6992  -16 -16
178056 6992  -16 -16
178156 6992  -16 -16
ipad disconnection detected
178157 disconnected ipad
178255 7632
178355 7632
178455 7632
178555 7632
178655 7632
178755 7632
178855 7632
178955 7632
179055 7632
179155 7632
179255 7632
179355 7632
179455 7632
179555 7632
179655 7632
179755 7632
179855 7632
179955 7632
180055 5104
180155 7632
180255 7632
180355 7632
180455 7632
180555 7632
180655 7520
180755 7520
180855 7520
180955 7520
181055 7520
181155 7520
181255 7520
181355 7520
181455 7520
181555 7520
181655 7520
181755 7520
181855 7520
181955 7520
182055 7520
182155 7520
182255 7520
182355 7520
182455 7520
182555 7520
182655 7520
182755 7520
182855 7520
182955 7520
183055 7520
183155 7520
183255 7520
183355 7520
183455 7520
183555 7520
183603 connected ipad
183656 6992  0 1152
183756 6992  0 1152
183856 5728  0 1152
183956 4464  0 1152
184056 3200  0 1152
184156 1936  0 1152
184256 672  -8 -8
184356 672  -8 -8
184456 672  -8 -8
184556 672  -8 -8
184656 672  -8 -8
184756 672  -8 -8
184856 672  -8 -8
184956 672  -8 -8
185056 672  -8 -8
185156 672  -8 -8
185256 672  -8 -8
185356 672  -8 -8
185456 672  -8 -8
185556 672  -8 -8
185656 672  -8 -8
185756 672  -8 -8
185856 672  -8 -8
185956 672  -8 -8
186056 672  -8 -8
186156 672  -8 -8
186256 672  -8 -8
186356 672  -8 -8
186456 672  -8 -8
186556 672  -8 -8
186656 672  -8 -8
186756 672  -8 -8
186856 672  -8 -8
186956 672  -8 -8
187056 672  -8 -8
187156 672  -8 -8
187256 672  -8 -8
ipad disconnection detected
187257 disconnected ipad
187355 1312
187455 1312
187555 1312
187655 1312