gilmaimon / ArduinoWebsockets

A library for writing modern websockets applications with Arduino (ESP8266 and ESP32)
GNU General Public License v3.0
482 stars 97 forks source link

Faster way to recognize no connection to WebSocket #103

Open kevinb5617 opened 3 years ago

kevinb5617 commented 3 years ago

Is your feature request related to a problem? Please describe.

I want my ESP32 to perform different functions if it can connect to a specific WebSocket or not. When I have my Django server running that the ESP32 is connecting to, it is able to connect fine with a call like

client.connect(server_ip, server_port, server_addr);

However, when my server is not turned on, I want the ESP to attempt to connect, fail immediately, then try again after say, 30 seconds. The issue, though, is the connect() call blocks for about 18 seconds before saying it could not connect. Since this program is for an embedded system, I would like to be able to keep a timer in the background and attempt to reconnect after 30 seconds, still allowing me to light up LEDs and perform other functions.

To simplify this question, when the connect() should fail (since the WebSocket server is down), is there any way for it to not block for 18 seconds?

Describe the solution you'd like

I looked in the existing library code, and there are no explicit timing functions that seem to force the program to block, although I'm not an expert in networking, especially with WebSockets.

Describe alternatives you've considered None

Additional context None

gilmaimon commented 3 years ago

Hi :) Thanks for opening this issue.

This is a good point, but the problem is that in my esp32 and esp8266 network implementation I'm very dependent on the underlying WiFiClient provided by the framework. I can't really think of a way for adding this kind of functionality without a risk of causing other issues and inconsistencies for users. Maybe you can use another library to ping the server?

That said, I am open for contributions and PRs. It's worth noting that this library is not actively developed by me these days, I'm just doing my best to maintain it and answer questions.

kevinb5617 commented 3 years ago

Thanks for your response! I'll definitely try to look at it for potential solutions. I'm using this for a school project so I can likely just call this a "prototype" version.

I'd be curious to try something like that just to ping the server for an immediate response. That way I can bypass the 18 seconds of blocking. I really like everything else with the library, though :) the latency I've found between sending messages over WebSockets on the ESP32 to a frontend is consistently <10 ms. I probably won't update anything in this specific library, but I'll put updates here for how I solved it.

gilmaimon commented 3 years ago

Cool :) And I glad you liked the library.

In retrospective there are many things I should have done differently, but I'm too lazy to refactor the code.. Maybe one day :)

kevinb5617 commented 3 years ago

Yep, I know the feeling. I used ArduinoJson too which worked really well with it too. We're making a "dog collar" that you can track on a website we're making, and you can draw fences on the website and the ESP will blink with lights when it goes out of the fence.

gasparfm commented 1 year ago

Years late, but I just came across this problem. It's related on how WiFiSecureClient (in my case) detects the connection (connected() method). (as @gilmaimon said). I think there's a bug, because this didn't work right (the internal connected variable wasn't updating when the connection is not alive). I changed it a little bit:

uint8_t WiFiClientSecure::connected()
{
  if (_connected) {
    uint8_t dummy = 0;
    int res = read(&dummy, 0);
    if (res<0) {
      switch (errno) {
        case EWOULDBLOCK:
        case ENOENT:
          _connected = true; 
          break;
        case ENOTCONN:
        case EPIPE:
        case ECONNRESET:
        case ECONNREFUSED:
        case ECONNABORTED:
          _connected = false; 
          log_d("Disconnected. RES: %d, ERRNO: %d\n", res, errno);
          break;
        default: 
          log_d("Unexpected. RES: %d, ERRNO: %d\n", res, errno);
          break;
      }
    }
  }
  return _connected;
}

It would be great if I could use with ArduinoWebsockets a custom class for WEBSOCKETS_NETWORK_CLASS / WEBSOCKETS_NETWORK_SSL_CLASS , so I could create a new MyWiFiSecureClient and override the function to avoid writing over the original WiFiSecureClient.cpp

gasparfm commented 1 year ago

You can also recognize this lack of connection using heartbeat :)