diff --git a/README.md b/README.md index f227c55..c1bd715 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino b/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino index 73451c5..0323cc1 100644 --- a/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino +++ b/examples/ESP_AsyncFSBrowser/ESP_AsyncFSBrowser.ino @@ -217,4 +217,5 @@ void setup(){ void loop(){ ArduinoOTA.handle(); + ws.cleanupClients(); } diff --git a/src/AsyncWebSocket.cpp b/src/AsyncWebSocket.cpp index fd1c7b8..d1b3eab 100644 --- a/src/AsyncWebSocket.cpp +++ b/src/AsyncWebSocket.cpp @@ -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) diff --git a/src/AsyncWebSocket.h b/src/AsyncWebSocket.h index 8e2954e..0234dd7 100644 --- a/src/AsyncWebSocket.h +++ b/src/AsyncWebSocket.h @@ -37,6 +37,12 @@ #include #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