Skip to content

TCP stays closed even after state changing to WL_CONNECTED with reconnecting WiFi #3224

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

Closed
Hieromon opened this issue Sep 18, 2019 · 2 comments
Labels
Status: Stale Issue is stale stage (outdated/stuck)

Comments

@Hieromon
Copy link

Hardware:

Board: ESP32 Development board
Core Installation/update date: 1.0.2, also 1.0.3
IDE name: Arduino IDE 1.8.9
Flash Frequency: 40MHz
PSRAM enabled: no
Upload Speed: 921600
Computer OS: Windows10

Description:

After reconnecting WiFi, it returns WL_CONNECTED but TCP remains closed. The order of events in which problems occur is as follows:

  • Set Static IP with WiFi.config and WIFI_STA.
  • The sketch established a connection with the router by WiFi.begin() once.
  • Restart the router while the sketch is running. ESP32 is disconnected.
  • STA_DISCONNECTED event occurred, detects disconnected reason as BEACON_TIMEOUT. There is no problem with this behavior.
  • The router has come up and re-establish the WiFi data link with ESP32. Detects STA_GOT_IP event and the IP will be restored.
  • After that, the HTTP request does not pass and does not respond to the Ping.
    At this time, WiFi.status() returns WL_CONNECTED, but TCP still seems to be closed.

This phenomenon doesn't occur in my environment, but it always happens in another user environment. It may be due to the reliability of a specific router, but for now, the cause is unknown.

Several issues similar to this issue have been discussed, but I would like to consider a countermeasure since the incompleteness of reconnection is still unresolved.

Is there an effective way to deal with this phenomenon?

Related issue #1464.
Hieromon/AutoConnect#121 as a source.

Sketch:

#include <WiFi.h>

#define SSID     "YOUR_SSID"
#define PASSWORD "YPUR_PASSWORD"

IPAddress local_IP(xxx, xxxx, xxx, xxx);
IPAddress gateway(xxx, xxxx, xxx, xxx);
IPAddress subnet(xxx, xxxx, xxx, xxx);
IPAddress DNS1(xxx, xxxx, xxx, xxx);
IPAddress DNS2(xxx, xxxx, xxx, xxx);

wl_status_t connectWiFi(const unsigned long timeout) {
  wl_status_t st;
  Serial.print("Connecting");
  // WiFi.begin(SSID, PASSWORD);
  WiFi.begin();
  unsigned long tm = millis();
  while ((st = WiFi.status()) != WL_CONNECTED) {
    if (millis() - tm > timeout)
      break;
    Serial.print('.');
    delay(300);
  }
  return st;
}

void setup() {
  delay(1000);
  Serial.begin(115200);
  Serial.println();
  
  WiFi.softAPdisconnect(true);
  WiFi.mode(WIFI_STA);
  delay(100);
  WiFi.setHostname("XXX");
  if (!WiFi.config(local_IP, gateway, subnet, DNS1, DNS2)) {
    Serial.println("WiFi.config failed");
    return;
  }
  if (connectWiFi(30000) == WL_CONNECTED) {
    Serial.println("connected:" + WiFi.localIP().toString());
  }
  else
    Serial.println("timeout");
  delay(3000);
}

void testClient(const char * host, uint16_t port) {
  Serial.print("\nconnecting to ");
  Serial.println(host);

  WiFiClient client;
  if (!client.connect(host, port)) {
    Serial.println("connection failed");
    return;
  }
  client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
  while (client.connected() && !client.available());
  while (client.available()) {
    Serial.write(client.read());
  }

  Serial.println("closing connection\n");
  client.stop();
}

void loop() {
  wl_status_t wifi_status = WiFi.status();

  if (wifi_status == WL_CONNECTED) {
    testClient("google.com", 80);
  }
  else
    Serial.println("No WiFi connection");
  delay(5000);
}

Log:

sorry for hard to see.

From initial behavior to router reset

64689544-2e6efd80-d4ac-11e9-9941-e0e3a6d40686 (1)

STA_GOT_IP detection and IP restoration,WiFiClient client.connect still fails

64690142-5743c280-d4ad-11e9-975b-812976047f4d

Preliminary diagnostics:

The arduino-esp32 core try reconnect with the WiFi.disconnect() and WiFi.begin() in the event handler. The above log indicates that its handler has executed and restored the IP, but subsequent HTTP GET failed.

The phenomenon occurred with the AutoConnect library, but I diagnosed using the following sketch without AutoConnect library to isolate the problem. It performs WiFi.reconnect() (Actually esp_wifi_disconnect and esp_wifi_connect) on the user sketch side after STA_DISCONNECTED detection (actually after WiFi.disconnected() and WiFi.begin() is executed by Arduino core).
As a result, HTTP GET was successful. So, I assume that TCP remains closed.

Test sketch with reconnection

#include <WiFi.h>

#define SSID     "YOUR_SSID"
#define PASSWORD "YPUR_PASSWORD"

IPAddress local_IP(xxx, xxxx, xxx, xxx);
IPAddress gateway(xxx, xxxx, xxx, xxx);
IPAddress subnet(xxx, xxxx, xxx, xxx);
IPAddress DNS1(xxx, xxxx, xxx, xxx);
IPAddress DNS2(xxx, xxxx, xxx, xxx);
wifi_event_id_t eventDiscon;
wifi_event_id_t eventGotIP;
wifi_event_id_t eventRescon;
bool staDiscon;
bool staGotIP;
bool rip;
unsigned long tmDiscon;

void cbDiscon(WiFiEvent_t e, WiFiEventInfo_t info) {
  Serial.println("[E] SYSTEM_EVENT_STA_DISCONNECTED");
  staDiscon = true;
  tmDiscon = millis();
}

void cbGotIP(WiFiEvent_t e, WiFiEventInfo_t info) {
  Serial.println("[E] SYSTEM_EVENT_STA_GOT_IP");
  staGotIP = true;
}

void onDiscon(void) {
  staDiscon = false;
  staGotIP = false;
  rip = false;
  eventDiscon = WiFi.onEvent(cbDiscon, SYSTEM_EVENT_STA_DISCONNECTED);
  eventGotIP = WiFi.onEvent(cbGotIP, SYSTEM_EVENT_STA_GOT_IP);
}

void removeEvent(void) {
  staDiscon = false;
  staGotIP = false;
  WiFi.removeEvent(eventDiscon);
  WiFi.removeEvent(eventGotIP);
}

void cbRescon(WiFiEvent_t e, WiFiEventInfo_t info) {
  Serial.println("[E] Connecttion restored");
  WiFi.removeEvent(eventRescon);
  onDiscon();
}

void restoreIP(unsigned long tmWhile) {
  if (!rip) {
    if (staDiscon & staGotIP) {
      if (millis() - tmDiscon > tmWhile) {
        rip = true;
        removeEvent();
        WiFi.reconnect();
        eventRescon = WiFi.onEvent(cbRescon, SYSTEM_EVENT_STA_GOT_IP);
      }
    }
  }
}

wl_status_t connectWiFi(const unsigned long timeout) {
  wl_status_t st;
  Serial.print("Connecting");
  // WiFi.begin(SSID, PASSWORD);
  WiFi.begin();
  unsigned long tm = millis();
  while ((st = WiFi.status()) != WL_CONNECTED) {
    if (millis() - tm > timeout)
      break;
    Serial.print('.');
    delay(300);
  }
  return st;
}

void setup() {
  delay(1000);
  Serial.begin(115200);
  Serial.println();
  
  WiFi.softAPdisconnect(true);
  WiFi.mode(WIFI_STA);
  delay(100);
  WiFi.setHostname("XXX");
  if (!WiFi.config(local_IP, gateway, subnet, DNS1, DNS2)) {
    Serial.println("WiFi.config failed");
    return;
  }
  if (connectWiFi(30000) == WL_CONNECTED) {
    Serial.println("connected:" + WiFi.localIP().toString());
    onDiscon();
  }
  else
    Serial.println("timeout");
  delay(3000);
}

void testClient(const char * host, uint16_t port) {
  Serial.print("\nconnecting to ");
  Serial.println(host);

  WiFiClient client;
  if (!client.connect(host, port)) {
    Serial.println("connection failed");
    return;
  }
  client.printf("GET / HTTP/1.1\r\nHost: %s\r\n\r\n", host);
  while (client.connected() && !client.available());
  while (client.available()) {
    Serial.write(client.read());
  }

  Serial.println("closing connection\n");
  client.stop();
}

void loop() {
  wl_status_t wifi_status = WiFi.status();

  if (wifi_status == WL_CONNECTED) {
    testClient("google.com", 80);
  }
  else
    Serial.println("No WiFi connection");

  restoreIP(5000);

  delay(5000);
}

Log for the above sketch executed.

WiFiClient client.connect immediately following STA_GOT_IP event fails once and restore with WiFi.reconnect().

No WiFi connection
[E] SYSTEM_EVENT_STA_DISCONNECTED
[E] SYSTEM_EVENT_STA_DISCONNECTED
[E] SYSTEM_EVENT_STA_DISCONNECTED
No WiFi connection
[E] SYSTEM_EVENT_STA_DISCONNECTED
[E] SYSTEM_EVENT_STA_DISCONNECTED
No WiFi connection
[E] SYSTEM_EVENT_STA_DISCONNECTED
[E] SYSTEM_EVENT_STA_DISCONNECTED
[E] SYSTEM_EVENT_STA_DISCONNECTED
No WiFi connection
[E] SYSTEM_EVENT_STA_DISCONNECTED
[E] SYSTEM_EVENT_STA_DISCONNECTED
No WiFi connection
[E] SYSTEM_EVENT_STA_DISCONNECTED
[E] SYSTEM_EVENT_STA_GOT_IP
[E] SYSTEM_EVENT_STA_GOT_IP

connecting to 172.217.27.174
connection failed
[E] Connecttion restored
[E] SYSTEM_EVENT_STA_GOT_IP
[E] SYSTEM_EVENT_STA_GOT_IP

connecting to 172.217.27.174
HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Fri, 13 Sep 2019 09:23:57 GMT
Expires: Sun, 13 Oct 2019 09:23:57 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219
X-XSS-Protection: 0
X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>
closing connection
@stale
Copy link

stale bot commented Nov 17, 2019

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Nov 17, 2019
@stale
Copy link

stale bot commented Dec 1, 2019

[STALE_DEL] This stale issue has been automatically closed. Thank you for your contributions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Stale Issue is stale stage (outdated/stuck)
Projects
None yet
Development

No branches or pull requests

1 participant