Skip to content

Websockets loop greatly slows down if a client WS lost due to Wifi dropout or change of SSID #922

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
computski opened this issue Dec 16, 2024 · 10 comments

Comments

@computski
Copy link

I have a websocket server running on an ESP8266. SSID = "something" Clients connect to something-WiFi, invoke a webpage and a websocket is established behind this. If the client closes the web page whilst still conneted to SSID-something, all is well. Multiple clients can connect/ disconnect like this.

BUT, if a client is on SSID-something with an open webpage (and so an open websocket) and then either the WiFi drops out or the client navigates to a different SSID-someOther then, after a few seconds, the whole websocket loop on the ESP greatly slows down permanently. The only recovery is a reboot.

Is there an error event I should handle? is there a way to detect 'lost clients' like this and terminate them on the ESP?

@setsunai-me
Copy link

I also encountered this problem. Didn't find a solution?

@computski
Copy link
Author

The issue is still open, the developer has not commented. I have not spent any time on a solution myself, possibly one could use the heartbeat mechanisms to detect a lost WS client and then execute a close on the client link.

@setsunai-me
Copy link

That's what I did yesterday. I used enableHeartbeat(2000, 1000, 3) and the problem seemed to be solved.

@computski
Copy link
Author

Hey good work. Can you post a code snippet showing the event handler you used along with enableHeartbeat. Thanks!

@setsunai-me
Copy link

setsunai-me commented Jan 29, 2025

I am writing a project for interaction via WI-FI between a device (ESP32) and a tablet (Android/Kotlin).

ESP32 is responsible for the WebSocket server in STA WI-FI mode (communication occurs via a Mikrotik router)

My problem was that the user with the tablet could move away to a long distance, due to which the connection to WI-Fi could be lost - this is how I came to the problem you described.

Without using heartbeat, I noticed that disconnection detection could occur only after 1-3 minutes.

Using heartbeat - disconnection detection occurs almost at the moment when the loss of connection to WI-FI began.

It also turned out that the problem was more in the broadcastTXT function (because there were definitely attempts to send a message even to actually disconnected clients).

Below is a piece of code that I use in my project to work with WebSocket.

I hope this information will help you move forward in solving your specific problem.

WebSocketsServer socket = WebSocketsServer(5555);
socket.begin();
socket.enableHeartbeat(2000, 1000, 3);
socket.onEvent([&, this](uint8_t num, WStype_t type, uint8_t* payload, size_t length) {
  if (type == WStype_DISCONNECTED) {
    Serial.println("Client ID" + String(num) + " has been disconnected");
  }
  if (type == WStype_CONNECTED) {
    if (this->syncReceiver) {
      this->syncReceiver(num);
    }
  } else if (type == WStype_TEXT) {
    String msg = this->parseMessage(payload, length);
    msg.trim();
    this->processMessage(msg, num);
  }
});

@Gord1
Copy link

Gord1 commented Mar 21, 2025

I have a similar problem. When the client computer is suspended or put to sleep, the server websocket loop slows to a crawl for the remaining clients. I've tried wsMonCPU.enableHeartbeat(5000, 1000, 3); but that doesn't seem to make any difference. Each main loop takes about 45 seconds, where normally it would be 0.018 seconds.

The heartbeat does not cause the disconnect of the client that drops off the network. The server still thinks that there are 2 clients attached although 1 has been shut down.
If you close the browser (e.g. use the x in the corner) the client is disconnected right away and things keep on working normally. It is only when the wifi drops or the client computer goes to sleep/turns off without closing the browser first.

After about 20-30 minutes of this crawling, it starts working normally again and is back to it's regular speed.

@Gord1
Copy link

Gord1 commented Mar 24, 2025

Ref. #881 (comment)
@SergeSkor

This is exactly the problem that I am experiencing.

@Gord1
Copy link

Gord1 commented Mar 24, 2025

If I have 2 clients connected to the WSserver running on an ESP8266 and one of the clients turns off the computer or tablet, the server only is able to send out 1 ws message every five seconds. The server still thinks that there are 2 clients attached even thought one has gone without closing the browser properly. 5 seconds is the WEBSOCKETS_TCP_TIMEOUT = 5000.

This is beyond my pay grade, so if anyone has suggestions ...

@Gord1
Copy link

Gord1 commented Mar 25, 2025

One thing that I have found is that when a client device gets disconnected from the server and the server times out the heartbeat counters are not reset. When the client device tries to reconnect the server immediately disconnects the client because the old values still exist and the HB missed count increases each time the the device tries to reconnect. The debug output is below:

(I have 2 websockets serving different parts of a webpage and I am broadcasting to all attached clients the information)

My HeartBeat for both servers is:
wsMonSerial.enableHeartbeat(5000, 1000, 3);
wsMonCPU.enableHeartbeat(5000, 1000, 3);

Each try at reconnecting the
[HBtimeout] pong TIMEOUT! lp=1535410 millis=1540910 pi=1026 count=7
increments and because it exceeds the allowable HB values above, it immediately disconnects.

21:16:09: [WS][0][sendFrame] pack to one TCP package...
21:16:09: [write] n: 243 t: 1540619
21:16:09: [WS][0][sendFrame] sending Frame Done (2455us).
21:16:09: [WS][1][sendFrame] not in WSC_CONNECTED state!?
21:16:09: [WS-Server][1][handleHeader] RX: Connection: Upgrade
21:16:10: [WS-Server][1][handleHeader] RX: Connection: Upgrade
21:16:10: [WS-Server][1][handleHeader] RX: Pragma: no-cache
21:16:10: [WS-Server][1][handleHeader] RX: Pragma: no-cache
21:16:10: [WS-Server][1][handleHeader] RX: Cache-Control: no-cache
21:16:10: [WS-Server][1][handleHeader] RX: Cache-Control: no-cache
21:16:10: [WS-Server][1][handleHeader] RX: User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
21:16:10: [WS-Server][1][handleHeader] RX: User-Agent: Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.36
21:16:10: handleFileRead: /edit/mode-html.js
21:16:10: [WS-Server][1][handleHeader] RX: Upgrade: websocket
21:16:10: [WS-Server][1][handleHeader] RX: Upgrade: websocket
21:16:10: Unknown sentence type.
21:16:10: [WS-Server][1][handleHeader] RX: Origin: http://tacktick.local
21:16:10: [WS-Server][1][handleHeader] RX: Origin: http://tacktick.local
21:16:10: handleFileRead: /index.htm
21:16:10: [WS-Server][1][handleHeader] RX: Sec-WebSocket-Version: 13
21:16:10: [WS-Server][1][handleHeader] RX: Sec-WebSocket-Version: 13
21:16:10: [WS-Server][1][handleHeader] RX: Accept-Encoding: gzip, deflate
21:16:10: [WS-Server][1][handleHeader] RX: Accept-Encoding: gzip, deflate
21:16:10: handleFileList: /
21:16:10: [WS-Server][1][handleHeader] RX: Accept-Language: en-US,en;q=0.9
21:16:10:
21:16:10: [HBtimeout] count=7, DISCONNECTING
21:16:10: [WS-Server][1] client disconnected.
21:16:10: [1] wsMonSerial Disconnected!
21:16:10: [WS-Server][1][handleHeader] RX: Accept-Language: en-US,en;q=0.9
21:16:10: [HBtimeout] pong TIMEOUT! lp=1535432 millis=1540932 pi=1039 count=5
21:16:10: [HBtimeout] count=5, DISCONNECTING
21:16:10: [WS-Server][1] client disconnected.
21:16:10: [1] wsMonCpu Disconnected!
21:16:10: handleStatus
21:16:10: handleFileRead: /edit/worker-html.js
21:16:10: [WS][0][sendFrame] ------- send message frame -------
21:16:10: [WS][0][sendFrame] fin: 1 opCode: 1 mask: 0 length: 71 headerToPayload: 0
21:16:10: [WS][0][sendFrame] text: ***** wsMonCPU ******* sending this text); // sent to CPU monitor page
21:16:10: [WS][0][sendFrame] pack to one TCP package...
21:16:10: [write] n: 73 t: 1541570
21:16:10: [WS][0][sendFrame] sending Frame Done (2737us).
21:16:10: [WS][0][sendFrame] ------- send message frame -------
21:16:10: [WS][0][sendFrame] fin: 1 opCode: 1 mask: 0 length: 239 headerToPayload: 0
21:16:10: [WS][0][sendFrame] text: ***** wsMonCPU ******* sending this:
21:16:10: Up Time: 00d 00:25:41
21:16:10: Web Clients: 1
21:16:10: Loop Duration:
21:16:10: Current: 1 ms
21:16:10: Last Sec: 315 ms
21:16:10: Max: 2412 ms
21:16:10: Heap:
21:16:10: Free Heap: 33840
21:16:10: Max Free Block: 30232
21:16:10: Heap Frag: 11
21:16:10: File Sys:
21:16:10: Size: 2072576
21:16:10: Used: 1
21:16:10: [WS][0][sendFrame] pack to one TCP package...
21:16:10: [write] n: 243 t: 1541615
21:16:10: [WS][0][sendFrame] sending Frame Done (2458us).

21:20:37: [WS-Server][1][handleHeader] RX: Upgrade: websocket
21:20:37: [WS-Server][1][handleHeader] RX: Upgrade: websocket
21:20:37: handleFileRead: /index.htm
21:20:37: [WS-Server][1][handleHeader] RX: Origin: http://tacktick.local
21:20:37: [WS-Server][1][handleHeader] RX: Origin: http://tacktick.local
21:20:37: [WS-Server][1][handleHeader] RX: Sec-WebSocket-Version: 13
21:20:37: [WS-Server][1][handleHeader] RX: Sec-WebSocket-Version: 13
21:20:37: handleFileList: /
21:20:37: [WS-Server][1][handleHeader] RX: Accept-Encoding: gzip, deflate
21:20:37: [HBtimeout] pong TIMEOUT! lp=1802548 millis=1808048 pi=1014 count=8
21:20:37: [HBtimeout] count=8, DISCONNECTING
21:20:37: [WS-Server][1] client disconnected.
21:20:37: [1] wsMonSerial Disconnected!
21:20:37: [WS-Server][1][handleHeader] RX: Accept-Encoding: gzip, deflate
21:20:37: [HBtimeout] pong TIMEOUT! lp=1802571 millis=1808071 pi=1028 count=6
21:20:37: [HBtimeout] count=6, DISCONNECTING
21:20:37: [WS-Server][1] client disconnected.
21:20:37: [1] wsMonCpu Disconnected!
21:20:37: handleStatus
21:20:37: handleFileRead: /favicon.ico
21:20:37: handleFileRead: /edit/worker-html.js
21:20:37: [WS-Server][0] sending HB ping
21:20:37: [WS][0][sendFrame] ------- send message frame -------
21:20:37: [WS][0][sendFrame] fin: 1 opCode: 9 mask: 0 length: 0 headerToPayload: 0
21:20:37: [write] n: 2 t: 1808543
21:20:37: [WS][0][sendFrame] sending Frame Done (2522us).
21:20:37: [WS][0][handleWebsocketWaitFor] size: 2 cWsRXsize: 0
21:20:37: [readCb] n: 2 t: 1808556
21:20:37: [WS][0][handleWebsocketWaitFor][readCb] size: 2 ok: 1
21:20:37: [WS][0][handleWebsocket] ------- read massage frame -------
21:20:37: [WS][0][handleWebsocket] fin: 1 rsv1: 0 rsv2: 0 rsv3 0 opCode: 10
21:20:37: [WS][0][handleWebsocket] mask: 1 payloadLen: 0
21:20:37: [WS][0][handleWebsocketWaitFor] size: 6 cWsRXsize: 2
21:20:37: [readCb] n: 4 t: 1808583
21:20:37: [WS][0][handleWebsocketWaitFor][readCb] size: 6 ok: 1
21:20:37: [WS][0][handleWebsocket] ------- read massage frame -------
21:20:37: [WS][0][handleWebsocket] fin: 1 rsv1: 0 rsv2: 0 rsv3 0 opCode: 10

21:20:58: handleFileList: /
21:20:58: [WS-Server][1][handleHeader] RX: Accept-Language: en-US,en;q=0.9
21:20:58: [HBtimeout] pong TIMEOUT! lp=1823566 millis=1829066 pi=1024 count=9
21:20:58: [HBtimeout] count=9, DISCONNECTING
21:20:58: [WS-Server][1] client disconnected.
21:20:58: [1] wsMonSerial Disconnected!
21:20:58: [WS-Server][1][handleHeader] RX: Accept-Language: en-US,en;q=0.9
21:20:58: [HBtimeout] pong TIMEOUT! lp=1823589 millis=1829089 pi=1038 count=7
21:20:58: [HBtimeout] count=7, DISCONNECTING
21:20:58: [WS-Server][1] client disconnected.
21:20:58: [1] wsMonCpu Disconnected!
21:20:58: handleFileRead: /edit/worker-html.js
21:20:58: handleStatus
21:20:58: [WS-Server][0] sending HB ping
21:20:58: [WS][0][sendFrame] ------- send message frame -------
21:20:58: [WS][0][sendFrame] fin: 1 opCode: 9 mask: 0 length: 0 headerToPayload: 0
21:20:58: [write] n: 2 t: 1829492
21:20:58: [WS][0][sendFrame] sending Frame Done (2326us).

@Gord1
Copy link

Gord1 commented Mar 31, 2025

I forked this and made changes to get this problem solved.

https://github.com/Gord1/arduinoWebSockets

Pull request made.
This issue is closed for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants