How to detect interrupted closed TCP connection?

Hello,

we have a TCPServer set up on Photon (2.0.0) and multiple clients (phones) connected to it over local wifi. We can keep only 5 connections opened (Photon’s limitation), so we are looking for a way how to detect and close the inactive connections in order to free slots for the other phones.

We tried two approaches:

  1. periodically check the TCP connection status via client.status() - in case it is 0, close the connection. This works when the connection is closed correctly by client, however doesnt work when the connection is closed incorrectly (lost wifi - phone cant ask Photon first to close the connection). The client.status() is 1 even when the phone is disconnected from the wifi.

Minimal example below - it writes client.status to Serial every second. So first, connect to it over telnet (you will see “1” printed over serial), then disconnect the device with open telnet from wifi and you will see “1” still coming over serial - Photon didn’t recognize the connection was closed.

#include "Particle.h"
// EXAMPLE USAGE

// telnet defaults to port 23
TCPServer server = TCPServer(23);
TCPClient client;
int last = 0;

void setup(){
  // start listening for clients
  server.begin();
  // Make sure your Serial Terminal app is closed before powering your device
  Serial.begin(9600);
  // Wait for a USB serial connection for up to 30 seconds
  waitFor(Serial.isConnected, 30000);
}

void loop(){
  if (client.status()) {
      //client connected, do nothing
  } else {
    // if no client is yet connected, check for a new connection
    client = server.available();
  }
  if ((millis()-last) > 1000) { // every second print status info
      last = millis();

      Serial.println(String(client.status()));
  }
}
  1. approach - we tried to implement kind of “keep alive” feature, sending data to the socket periodically and detect errors. This works, but it is very intensive on RAM as the data that were not sent are kept in buffers in RAM and each connection needs around 6kB of RAM. This RAM is unfortunately not freed after the connection is close in the code, so going this way means we run out of memory on Photon very quickly…

It’s not possible to detect that a TCP client has disappeared because by default there is no keep-alive over TCP, and thus there is no way for the server side to know that the client is no longer there.

Ideally you have the client side periodically send data. If the server side does not receive anything from the client in the specific time window, then it knows the client went away. This won’t be affected by the transmit retry buffer.

If you need to send data from the server (Photon) side, you can interrupt the process before the buffer is full. Use the availableForWrite call to keep track of how much buffer space is available. If the available bytes keep getting smaller, the client has stopped acknowledging them so you should be able to client.stop() and free the transmit buffers.

Hi! Thank you very much for the reply.

I will try the availableForWrite call and let you know.

I thought it is just for serial communication, not TCP…

You’re right, we don’t expose the remaining buffer available on TCP connections. I couldn’t find a workaround.

OK, we go the way of identifying the oldest connection. Is there some kind of keep alive for TCP connection on a roadmap? Because with <10 connections and no RAM-easy way to detect the dead connections, the TCP server is quite difficult to run…

Thank you!