Scenario:
Esp8266 module in SoftAP mode acts as a TCP<->Serial bridge.
Client connects and sends commands by TCP which are translated to serial.
Serial server responds to command and returns serial data.
The loop() detects new incoming serial data and reads these, then sends it out the tcp client socket.
Somewhere in the meantime the TCP socket client disconnects or is lost due to network issues
I want to detect this case, but I don't know how.
Is there a way to detect if a client that was connected has disconnected?
When a client connects there is a way to see this in the code snippet below, but how should the disconnection be handled? I took the code from an example sketch and expanded it a bit when building my solution.
void loop()
{
uint8_t i;
char buf[1024], cnfBuf[100];
unsigned int bytesAvail, bytesIn, cnfBytesAvail, cnfBytesIn, cnfBytesOut;
//check if there are any new clients
if (tcpServer->hasClient()) {
for (i = 0; i < MAX_SRV_CLIENTS; i++) {
//find free/disconnected spot
if (!tcpServerClients[i] || !tcpServerClients[i].connected()) {
if (tcpServerClients[i]) tcpServerClients[i].stop();
tcpServerClients[i] = tcpServer->available();
SerialDebug.print("New client: "); SerialDebug.println(i);
continue;
}
}
//no free/disconnected spot so reject
WiFiClient tcpServerClient = tcpServer->available();
tcpServerClient.stop();
}
It looks like this code by itself disconnects clients:
tcpServerClient.stop();
But I don't fully understand this part of the sketch.
I would like to send a SerialDebug message to indicate when a client has disconnected from the AP.
And also reduce an internal count of connected clients.
Or is the whole concept of connected clients flawed? I cannot very well make a transaction based systemon esp8266 level where the client connects for each command and the server disconnects him after having sent back the response, because since this is a relaying TCP<->Serial function the esp8266 cannot know when the serial server has completed a transaction.
So the only way would be for the TCP client to disconnect between every transaction leading to this sequence:
Client needs to perform a transaction
Client connects by TCP to the esp8266
Client sends the command
Client awaits command reply (determined by the serial server responsiveness)
Client receives result data and determines if the transaction is completed
Client disconnects the socket
Server (esp8266) detects the disconnection and decrements client counter
But if this repeats for many transactions it may well become inefficient because of the constant overhead of TCP socket connect/disconnect.
And I still would have to know esp8266 server side when the client has disconnected...
Can the esp8266 TCP server detect a disconnection instantly?
the snippet handles all concurrent clients of the server, but the count is limited so some clients are rejected with stop (server side connection close).
to test if the client is alive, you can use client.connected() or client.status().
I would handle only one client at the time, not all connected clients like in the snippet.
if (!client) {
client = server.available();
}
if (client && !client.connected())
client.stop();
client = server.available();
}
Juraj:
the snippet handles all concurrent clients of the server, but the count is limited so some clients are rejected with stop (server side connection close).
to test if the client is alive, you can use client.connected() or client.status().
I would handle only one client at the time, not all connected clients like in the snippet.
I am back at this problem now after having created the WiFi board with an ESP-07S module...
client.connected() seems not to change if the client loses connection (out of range or suddenly powered off)
client.status(): What can it report?
The use case of our system is this:
WiFi board is an interface between a data collection system using RS232 and the network
The WiFi board implements a softAP to which an Android device connects
The WiFi board runs an UART-TCP bridge as described above. It does not know about the data protocol.
After connecting to the softAP the Android device App opens a TCP socket towards the WiFi board
Then it starts controlling the data collection system by sending commands and receiving responses (all binary)
The App will need to control the system for hours and data are not transferred constantly, could be many minutes between transfers.
I can limit the allowed clients to one as you state, since there is only one serial port on the ESP8266.'
But the problem remains.
The problem:
If the Android device moves outside of the AP range the network gets disconnected and the socket is lost too.
When the Android device is back in range the App will try to reconnect WiFi and then also the TCP connection.
But now the WiFi device will have a problem because it has not detected that the TCP client disappeared and is now re-connecting. So the code to attach a new client will fail since it will consider the single available slot already occupied (if MAX_SRV_CLIENTS = 1) even though it has lost the connection.
AFAICT the tcpServerClients[ i ].connected() property is not reset in this case and thus indicates that the connection is still up. Therefore there is no free spot to connect to and the connection call is refused....
What can be done in this case?
Maybe by modifying the connection sequence such that it will record the MAC address of the accepted client and then when the reconnect arrives if it is from the same MAC address it will be accepted and the new client will replace the old client in the array?
But then how does one read the MAC address of the remote client?
I can only find a property for the IP address of the client and that will probably always be the same irrespective of the actual client (supplied by the SoftAP DHCP function).
This disconnect/reconnect issue is a show-stopper for our use of the EPP-07S device...
Furtermore:
How can I detect on the Arduino side that the client disconnected by doing a proper socket disconnect/close?
In that case I would like to reset the saved MAC address etc to prepare for a new connection from scratch.