Add function so that the total number of web-socket clients can be limited (#591)

* Add function so that the total number of web-socket clients can be limited easily.  This is to cope with a problem when a browser does not close the web-socket connection correctly.  I have observed this on Chromium based browsers.  The memory leak will eventually lead to the server crashing.  Normally only one connection per client is required, so limiting the number of connections would not normally cause any problems.

* Prevent an assertion failure when using WebSockets

Frequently when using Web Sockets you will get the assert failure:
    	assertion "new_rcv_ann_wnd <= 0xffff" failed: file "/Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/lwip/lwip/src/core/tcp.c", line 779, function: tcp_update_rcv_ann_wnd

This will happen particulary when you close the browser window.  This change
prevents the issue from occuring.

* Do not use thread locking with the ESP8266, but instead use an empty placeholder class that can be used to implement locking at a later date.

* Do not use thread locking with the ESP8266, but instead use an empty placeholder class that can be used to implement locking at a later date.

* Add function so that the total number of web-socket clients can be limited easily.  This is to cope with a problem when a browser does not close the web-socket connection correctly.  I have observed this on Chromium based browsers.  The memory leak will eventually lead to the server crashing.  Normally only one connection per client is required, so limiting the number of connections would not normally cause any problems.

* Set the default number of ws clients dependent on processor.
This commit is contained in:
matt123p 2019-09-24 20:42:40 +01:00 committed by Me No Dev
parent f5ee1935c5
commit 2f37037029
4 changed files with 26 additions and 0 deletions

View File

@ -79,6 +79,7 @@ To use this library you might need to have the latest git versions of [ESP32](ht
- [Async WebSocket Event](#async-websocket-event)
- [Methods for sending data to a socket client](#methods-for-sending-data-to-a-socket-client)
- [Direct access to web socket message buffer](#direct-access-to-web-socket-message-buffer)
- [Limiting the number of web socket clients](#limiting-the-number-of-web-socket-clients)
- [Async Event Source Plugin](#async-event-source-plugin)
- [Setup Event Source on the server](#setup-event-source-on-the-server)
- [Setup Event Source in the browser](#setup-event-source-in-the-browser)
@ -1126,6 +1127,16 @@ void sendDataWs(AsyncWebSocketClient * client)
}
```
### Limiting the number of web socket clients
Browsers sometimes do not correctly close the websocket connection, even when the close() function is called in javascript. This will eventually exhaust the web server's resources and will cause the server to crash. Periodically calling the cleanClients() function from the main loop() function limits the number of clients by closing the oldest client when the maximum number of clients has been exceeded. This can called be every cycle, however, if you wish to use less power, then calling as infrequently as once per second is sufficient.
```cpp
void loop(){
ws.cleanupClients();
}
```
## Async Event Source Plugin
The server includes EventSource (Server-Sent Events) plugin which can be used to send short text events to the browser.
Difference between EventSource and WebSockets is that EventSource is single direction, text-only protocol.

View File

@ -217,4 +217,5 @@ void setup(){
void loop(){
ArduinoOTA.handle();
ws.cleanupClients();
}

View File

@ -927,6 +927,13 @@ void AsyncWebSocket::closeAll(uint16_t code, const char * message){
}
}
void AsyncWebSocket::cleanupClients(uint16_t maxClients)
{
if (count() > maxClients){
_clients.front()->close();
}
}
void AsyncWebSocket::ping(uint32_t id, uint8_t *data, size_t len){
AsyncWebSocketClient * c = client(id);
if(c)

View File

@ -37,6 +37,12 @@
#include <Hash.h>
#endif
#ifdef ESP32
#define DEFAULT_MAX_WS_CLIENTS 8
#else
#define DEFAULT_MAX_WS_CLIENTS 4
#endif
class AsyncWebSocket;
class AsyncWebSocketResponse;
class AsyncWebSocketClient;
@ -255,6 +261,7 @@ class AsyncWebSocket: public AsyncWebHandler {
void close(uint32_t id, uint16_t code=0, const char * message=NULL);
void closeAll(uint16_t code=0, const char * message=NULL);
void cleanupClients(uint16_t maxClients = DEFAULT_MAX_WS_CLIENTS);
void ping(uint32_t id, uint8_t *data=NULL, size_t len=0);
void pingAll(uint8_t *data=NULL, size_t len=0); // done