gilmaimon / ArduinoWebsockets

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

Reconnection problems #95

Open gdhgdhgdh opened 3 years ago

gdhgdhgdh commented 3 years ago

ESP8266 with Arduino 1.8.13, ArduinoWebsockets 0.5.0

I was reading #75 because I'm having the same probem. I have put my websocket setup calls into its own function:


void onEventsCallback(WebsocketsEvent event, String data) {
    if(event == WebsocketsEvent::ConnectionOpened) {
        Serial.println("Connnection Opened");
    } else if(event == WebsocketsEvent::ConnectionClosed) {
        Serial.println("Connnection Closed");
        setupWebsocket();
    }
}

void setupWebsocket() {
    client = {}; // as advised in issue #75 
    client.onMessage(onMessageCallback);
    client.onEvent(onEventsCallback);
    client.setInsecure(); // yes, lame
    client.connect(websockets_connection_string);
}

void setup() {
// [..  Serial + wifi setup not shown..]

    setupWebsocket();
}

This works fine until the remote websocket is closed - my code does not successfully reconnect :( I DO see the Connection Closed and then shortly after Connection Opened on the Serial output, but I don't get any new incoming WS messages after that.

What am I doing wrong?

gilmaimon commented 3 years ago

I guess the problem might be a bug in the copy c'tor of the client class. I wrote this code so long ago, looking at it today it looks like a disaster... Anyways, I recommend avoiding the copy c'tor completely and really allocating a new object. So have the object on the heap and do

delete clientPtr;
clientPtr = new WebsocketsClient(...)

It's a terrible answer, but I think it might be the issue. If anyone wants to jump in and fix this in the library, it is a welcomed contribution. Possible fixes are either refactoring the copy c'tors to include all members, or to just =delete them completely (breaking some user code, but probably fixing so many issues...)

gdhgdhgdh commented 3 years ago

Ah thanks for the suggestions.

My C programming days only allow me the faintest grasp of structs, object instantiation and pointer - I threw a bunch of * and & and when it compiled, I only ended up in an ESP8266 loop. I'm happy to simply accept that my little project won't gracefully reconnect :)

abhishekthalatoty commented 3 years ago

I guess the problem might be a bug in the copy c'tor of the client class. I wrote this code so long ago, looking at it today it looks like a disaster... Anyways, I recommend avoiding the copy c'tor completely and really allocating a new object. So have the object on the heap and do

It's a terrible answer, but I think it might be the issue. If anyone wants to jump in and fix this in the library, it is a welcomed contribution. Possible fixes are either refactoring the copy c'tors to include all members, or to just =delete them completely (breaking some user code, but probably fixing so many issues...)

Hello! Firstly, I just wanna say thanks for this amazing library.

I have been facing the same issue mentioned here. Instead of keeping the same connection alive with a ping, I want to open a new connection and use that. The Connection opens but doesn't receive any messages.

How exactly is it related to Copy Constructor though? I've commented out one of the copy c'tors but there's no change. And it looks like most of the members, except for functions like onMessage are being copied, and since the setup function is calling onMessage again, I don't think that should be a problem. I would like to work on this, but I think I'll be needing some guidance. What other changes should I be doing to get it working?

Thanks again.

shardul10 commented 9 months ago

Has anyone been able to reconnect after lost connection? Would appreciate a solution.

lukesmolo commented 9 months ago

Following @gilmaimon 's suggestion, I simply added this code to instantiate a new Client before the reconnection, so I was able to reconnect and resume the sending of messages to the server. Let's assume we have declared client as a global variable.

WebsocketsClient* clientPtr = &client;
delete clientPtr;
client =  *(new WebsocketsClient());
shardul10 commented 9 months ago

Thank you @lukesmolo. I will try this.

git-eri commented 8 months ago

@lukesmolo Could you give more explanation on your solution? I am struggeling to implement your snippet to work with reconnections. How did you declare client and is that snippet just for the loop if the conenction fails? I am trying to implement this into the Esp8266-Client.ino. When i try this the ESP seems to completely reboot, that must be wrong?

AiziChen commented 6 months ago

@lukesmolo It is not working for my ESP32 project, reconnection issue still apear.

AviStudio commented 6 months ago

@lukesmolo Please show us the full code....

gmm932 commented 4 months ago

I need solution for this problem too!

markosole commented 3 months ago

Hiya, I am looking into same solution,. For not I am using detection in the loop and works well. It's not optimal but does the job for now:


bool isConnected;

void loop() {
  client.poll();

  // Check connection status and attempt reconnection if needed
  if (!isConnected && WiFi.status() == WL_CONNECTED) {
    Serial.println("Connection closed, attempting reconnect...");
    if (client.connect(websockets_server_host, websockets_server_port, "/")) {
      isConnected = true;
      Serial.println("Reconnected successfully!");
      // Optionally, send a message after reconnection
      client.send("ESP32 reconnected!");
    } else {
      Serial.println("Reconnection failed, retrying in 5 seconds...");
      delay(5000); // Wait 5 seconds before retrying
    }
  } else if (isConnected) {
    // Send a ping every 10 seconds to check server responsiveness
    static unsigned long lastPingTime = 0;
    if (millis() - lastPingTime > 10000) {
      client.ping();
      lastPingTime = millis();
    }

    // Check for missed pong response (indicating potential server unavailability)
    if (client.available() > 0) { // Check if there's data available to be written (pongs)
      //client.flush(); // Flush any pending data (including pongs)
    } else {
      Serial.println("Server seems unresponsive, attempting reconnect...");
      isConnected = false; // Trigger reconnection logic
    }
  }
}

And @lukesmolo what your solution looks like with using what you've suggested?

WebsocketsClient* clientPtr = &client;
delete clientPtr;
client =  *(new WebsocketsClient());

Thanks!