espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.75k stars 7.43k forks source link

[D][WiFiClient.cpp:452] connected(): Disconnected: RES: 0, ERR: 128 problem? #1921

Closed nae9 closed 3 years ago

nae9 commented 6 years ago

Hardware:

Board: ttgo (and other) Core Installation/update date: 10/3/2018 IDE name: Arduino IDE 1.8.7 Flash Frequency: 80Mhz PSRAM enabled: no Upload Speed: 115200 Computer OS: Windows 10

Description:

I try to install new release of arduino-esp and faced with some picularities in my sketch behavior. win 10, arduino 1.8.7 , esptool 2.3.1, mkspiffs 0.2.3, xtensa 1.22.0-80-g6c443a-5.2.0. TTGO board. Early all work fine - i send HTTP packets from PC to ESP32 and recieve answer about 30 "fps". But after i install new version of IDF (download by arduino "https://dl.espressif.com/dl/package_esp32_index.json") then answer not sends or sends with long timeouts. It seemed that new wificlient.cpp work different in compare with old version. For example i try to use standard arduino example like SimpleWiFiServer.ino and they also freeze answers... I print IP adress of esp32 in mozilla firefox (or another program) and after about 3-5 sec i see in debug that HTTP recieved by ESP32 and answered, mozilla some time recive answer, but some time no. Early answer returned very fast. After i see in debug "client disconnected" then after 100ms i see "new client"! but client.available() == 0 and program spin in while(client.connected()) cycle. Then are timeout event (?) after 5-10sec [D][WiFiClient.cpp:452] connected(): Disconnected: RES: 0, ERR: 128 and client.connected == 0 - program moove later. The analysis of debug output shows that client.stop() command not make client.connected() == 0 and in second cycle we catch in infinite while(client.connected()) loop.

What i do wrong? How i can do fast series of HTTP request/answer to esp32? Why in old version (06/2017) all was fine?

Sketch: (leave the backquotes for code formatting)


//Change the code below by your sketch
#include <WiFi.h>
const char* ssid     = "myssid";
const char* password = "mypass";
WiFiServer server(80);

void setup()
{
  Serial.begin(115200);
  pinMode(5, OUTPUT);      // set the LED pin mode
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
}

int value = 0;

void loop() {
  WiFiClient client = server.available();   // listen for incoming clients

  if (client) {                             // if you get a client,
    Serial.println("New Client.");           // print a message out the serial port
    String currentLine = "";                // make a String to hold incoming data from the client
    while (client.connected()) {            // loop while the client's connected
      if (client.available()) {             // if there's bytes to read from the client,
        char c = client.read();             // read a byte, then
        Serial.write(c);                    // print it out the serial monitor
        if (c == '\n') {                    // if the byte is a newline character

          // if the current line is blank, you got two newline characters in a row.
          // that's the end of the client HTTP request, so send a response:
          if (currentLine.length() == 0) {
            // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
            // and a content-type so the client knows what's coming, then a blank line:
            // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("Connection: close");  // the connection will be closed after completion of the response
            //client.println("Refresh: 5");  // refresh the page automatically every 5 sec
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
              client.print("analog input ");
              client.print("AI0");
              client.print(" is ");
              client.print(analogRead(A0));
              client.println("<br />");
            client.println("</html>");
            break;
          } else {    // if you got a newline, then clear currentLine:
            currentLine = "";
          }
        } else if (c != '\r') {  // if you got anything else but a carriage return character,
          currentLine += c;      // add it to the end of the currentLine
        }

        // Check to see if the client request was "GET /H" or "GET /L":
        if (currentLine.endsWith("GET /H")) {
          digitalWrite(5, HIGH);               // GET /H turns the LED on
        }
        if (currentLine.endsWith("GET /L")) {
          digitalWrite(5, LOW);                // GET /L turns the LED off
        }
      }
    }

    // close the connection:
    client.stop();
    Serial.println("Client Disconnected.");
  }
}

Debug Messages:

ets Jun  8 2016 00:22:57
17:52:57.076 -> 
17:52:57.076 -> rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
17:52:57.076 -> configsip: 0, SPIWP:0xee
17:52:57.076 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
17:52:57.076 -> mode:DIO, clock div:1
17:52:57.076 -> load:0x3fff0018,len:4
17:52:57.116 -> load:0x3fff001c,len:952
17:52:57.116 -> load:0x40078000,len:6084
17:52:57.116 -> load:0x40080000,len:7936
17:52:57.116 -> entry 0x40080310

17:52:57.316 -> 
17:52:57.316 -> Connecting to nae
[D][WiFiGeneric.cpp:345] _eventCallback(): Event: 2 - STA_START
17:52:57.396 -> [D][WiFiGeneric.cpp:345] _eventCallback(): Event: 0 - WIFI_READY
.[D][WiFiGeneric.cpp:345] _eventCallback(): Event: 4 - STA_CONNECTED
[D][WiFiGeneric.cpp:345] _eventCallback(): Event: 7 - STA_GOT_IP
17:52:58.396 -> [D][WiFiGeneric.cpp:389] _eventCallback(): STA IP: 192.168.1.210, MASK: 255.255.255.0, GW: 192.168.1.1
17:52:58.396 -> .
17:52:58.396 -> WiFi connected.
17:52:58.396 -> IP address: 
17:52:58.396 -> 192.168.1.210
New Client.
17:53:51.764 -> GET / HTTP/1.1
17:53:51.764 -> Host: 192.168.1.210
17:53:51.764 -> User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
17:53:51.764 -> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
17:53:51.804 -> Accept-Language: en-US,en;q=0.5
17:53:51.804 -> Accept-Encoding: gzip, deflate
17:53:51.804 -> Connection: keep-alive
17:53:51.804 -> Upgrade-Insecure-Requests: 1
17:53:51.804 -> 
Client Disconnected.
17:53:51.884 -> New Client.
[D][WiFiClient.cpp:452] connected(): Disconnected: RES: 0, ERR: 128
Client Disconnected.
nae9 commented 6 years ago

I check old version work setup: Early i use installation in UserDocuments/Arduino/Hardware/espressif/esp32/... and i have bakup of this folder "https://drive.google.com/file/d/1-4Ab6572dV7KypVEbPMz9a8yU7l_Db8c/view?usp=sharing". (this is old version of esp32 ambient with old wifi libs)

Copy this into UserDocuments/Arduino/hardware/espressif/esp32/ If you use additional libs then put it in UserDocuments/Arduino/libraries/ Your skethes put in UserDocuments/Arduino/ Install Arduino 1.8.7 (or other) Clear c:\Users\UserName\AppData\Local\Arduino15\ Set in arduino IDE props sketch folder as "UserDocuments/Arduino/" and reload IDE.

raico-de commented 6 years ago

It is not a solution to use a lib from last year, i have still the same problem: [D][WiFiClient.cpp:453] connected(): Disconnected: RES: 0, ERR: 128 [D][WiFiClient.cpp:453] connected(): Disconnected: RES: 0, ERR: 128

other problem is the function

size_t WiFiClient::write_P(PGM_P buf, size_t size) { return write(buf, size); } if you use write there is a type conflict:

invalid arguments ' Candidates are: ? write(?) unsigned int write(const char ) ? write(const ? , ?) ? write(const char , ?) unsigned int write(unsigned char) unsigned int write(const unsigned char , unsigned int) unsigned int write(Stream &) '

GeorgeFlorian commented 5 years ago

This is still an issue. I've downloaded the latest Arduino Core for ESP32, the newest libraries and I still get this error: [D][WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128

nae9 commented 5 years ago

I find a method that fix this strange behavior... https://github.com/espressif/arduino-esp32/issues/2345

GeorgeFlorian commented 5 years ago

I find a method that fix this strange behavior... #2345

I don't understand where or what.

nae9 commented 5 years ago

Click on #2345 tag and read! Briefly:

void setup() { ... WiFi.begin(ssid, password); WiFi.setSleep(false);// <--- this command disables WiFi energy save mode and eliminate connected(): Disconnected: RES: 0, ERR: 128 problem ... }

GeorgeFlorian commented 5 years ago

Click on #2345 tag and read! Briefly:

void setup() { ... WiFi.begin(ssid, password); WiFi.setSleep(false);// <--- this command disables WiFi energy save mode and eliminate connected(): Disconnected: RES: 0, ERR: 128 problem ... }

WiFi.setSleep(false); doesn't work for me. I also don't have a WiFi.begin(ssid, password); Here is the code. I'm trying to implement Hieromon's AutoConnect and FSBrowser. From what I know AutoConnect handles WiFi.begin(ssid, password); and maybe that is why it doesn't work.

/*
  FSWebServer - Example WebServer with FS backend for esp8266/esp32
  Copyright (c) 2015 Hristo Gochkov. All rights reserved.
  This file is part of the WebServer library for Arduino environment.
  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  upload the contents of the data folder with MkSPIFFS Tool ("ESP32 Sketch Data Upload" in Tools menu in Arduino IDE)
  or you can upload the contents of a folder if you CD in that folder and run the following command:
  for file in `ls -A1`; do curl -F "file=@$PWD/$file" esp32fs.local/edit; done
  access the sample web page at http://esp32fs.local
  edit the page by going to http://esp32fs.local/edit
*/
#include <FS.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <AutoConnect.h>

#define FILESYSTEM SPIFFS
#define FORMAT_FILESYSTEM false
#define DBG_OUTPUT_PORT Serial

#define LED 2

#if FILESYSTEM == FFat
#include <FFat.h>
#endif
#if FILESYSTEM == SPIFFS
#include <SPIFFS.h>
#endif

const char* ssid = "wifi-ssid";
const char* password = "wifi-password";
const char* host = "esp32fs";

WebServer server(80);
AutoConnect portal(server);

//holds the current upload
File fsUploadFile;

bool startCP(IPAddress ip) {
    digitalWrite(LED, HIGH);
    DBG_OUTPUT_PORT.println("Captive Portal started ! IP: " + WiFi.localIP().toString());
    return true;
  }

//format bytes
String formatBytes(size_t bytes) {
  if (bytes < 1024) {
    return String(bytes) + "B";
  } else if (bytes < (1024 * 1024)) {
    return String(bytes / 1024.0) + "KB";
  } else if (bytes < (1024 * 1024 * 1024)) {
    return String(bytes / 1024.0 / 1024.0) + "MB";
  } else {
    return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB";
  }
}

String getContentType(String filename) {
  if (server.hasArg("download")) {
    return "application/octet-stream";
  } else if (filename.endsWith(".htm")) {
    return "text/html";
  } else if (filename.endsWith(".html")) {
    return "text/html";
  } else if (filename.endsWith(".css")) {
    return "text/css";
  } else if (filename.endsWith(".js")) {
    return "application/javascript";
  } else if (filename.endsWith(".png")) {
    return "image/png";
  } else if (filename.endsWith(".gif")) {
    return "image/gif";
  } else if (filename.endsWith(".jpg")) {
    return "image/jpeg";
  } else if (filename.endsWith(".ico")) {
    return "image/x-icon";
  } else if (filename.endsWith(".xml")) {
    return "text/xml";
  } else if (filename.endsWith(".pdf")) {
    return "application/x-pdf";
  } else if (filename.endsWith(".zip")) {
    return "application/x-zip";
  } else if (filename.endsWith(".gz")) {
    return "application/x-gzip";
  }
  return "text/plain";
}

bool exists(String path){
  bool yes = false;
  File file = FILESYSTEM.open(path, "r");
  if(!file.isDirectory()){
    yes = true;
  }
  file.close();
  return yes;
}

bool handleFileRead(String path) {
  DBG_OUTPUT_PORT.println("handleFileRead: " + path);
  if (path.endsWith("/")) {
    path += "index.htm";
  }
  String contentType = getContentType(path);
  String pathWithGz = path + ".gz";
  if (exists(pathWithGz) || exists(path)) {
    if (exists(pathWithGz)) {
      path += ".gz";
    }
    File file = FILESYSTEM.open(path, "r");
    server.streamFile(file, contentType);
    file.close();
    return true;
  }
  return false;
}

void handleFileUpload() {
  if (server.uri() != "/edit") {
    return;
  }
  HTTPUpload& upload = server.upload();
  if (upload.status == UPLOAD_FILE_START) {
    String filename = upload.filename;
    if (!filename.startsWith("/")) {
      filename = "/" + filename;
    }
    DBG_OUTPUT_PORT.print("handleFileUpload Name: "); DBG_OUTPUT_PORT.println(filename);
    fsUploadFile = FILESYSTEM.open(filename, "w");
    filename = String();
  } else if (upload.status == UPLOAD_FILE_WRITE) {
    //DBG_OUTPUT_PORT.print("handleFileUpload Data: "); DBG_OUTPUT_PORT.println(upload.currentSize);
    if (fsUploadFile) {
      fsUploadFile.write(upload.buf, upload.currentSize);
    }
  } else if (upload.status == UPLOAD_FILE_END) {
    if (fsUploadFile) {
      fsUploadFile.close();
    }
    DBG_OUTPUT_PORT.print("handleFileUpload Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
  }
}

void handleFileDelete() {
  if (server.args() == 0) {
    return server.send(500, "text/plain", "BAD ARGS");
  }
  String path = server.arg(0);
  DBG_OUTPUT_PORT.println("handleFileDelete: " + path);
  if (path == "/") {
    return server.send(500, "text/plain", "BAD PATH");
  }
  if (!exists(path)) {
    return server.send(404, "text/plain", "FileNotFound");
  }
  FILESYSTEM.remove(path);
  server.send(200, "text/plain", "");
  path = String();
}

void handleFileCreate() {
  if (server.args() == 0) {
    return server.send(500, "text/plain", "BAD ARGS");
  }
  String path = server.arg(0);
  DBG_OUTPUT_PORT.println("handleFileCreate: " + path);
  if (path == "/") {
    return server.send(500, "text/plain", "BAD PATH");
  }
  if (exists(path)) {
    return server.send(500, "text/plain", "FILE EXISTS");
  }
  File file = FILESYSTEM.open(path, "w");
  if (file) {
    file.close();
  } else {
    return server.send(500, "text/plain", "CREATE FAILED");
  }
  server.send(200, "text/plain", "");
  path = String();
}

void handleFileList() {
  if (!server.hasArg("dir")) {
    server.send(500, "text/plain", "BAD ARGS");
    return;
  }

  String path = server.arg("dir");
  DBG_OUTPUT_PORT.println("handleFileList: " + path);

  File root = FILESYSTEM.open(path);
  path = String();

  String output = "[";
  if(root.isDirectory()){
      File file = root.openNextFile();
      while(file){
          if (output != "[") {
            output += ',';
          }
          output += "{\"type\":\"";
          output += (file.isDirectory()) ? "dir" : "file";
          output += "\",\"name\":\"";
          output += String(file.name()).substring(1);
          output += "\"}";
          file = root.openNextFile();
      }
  }
  output += "]";
  server.send(200, "text/json", output);
}

void setup(void) {
  DBG_OUTPUT_PORT.begin(115200);
  DBG_OUTPUT_PORT.print("\n");
  DBG_OUTPUT_PORT.setDebugOutput(true);

  if (FORMAT_FILESYSTEM) FILESYSTEM.format();

  FILESYSTEM.begin();
  {
      File root = FILESYSTEM.open("/");
      File file = root.openNextFile();
      while(file){
          String fileName = file.name();
          size_t fileSize = file.size();
          DBG_OUTPUT_PORT.printf("FS File: %s, size: %s\n", fileName.c_str(), formatBytes(fileSize).c_str());
          file = root.openNextFile();
      }
      DBG_OUTPUT_PORT.printf("\n");
  }

  //WIFI INIT
  //DBG_OUTPUT_PORT.printf("Connecting to %s\n", ssid);
//  if (String(WiFi.SSID()) != String(ssid)) {
//    WiFi.mode(WIFI_STA);
//    WiFi.begin(ssid, password);
//  }
//
//  while (WiFi.status() != WL_CONNECTED) {
//    delay(500);
//    DBG_OUTPUT_PORT.print(".");
//  }

  //SERVER INIT
  //list directory
  server.on("/list", HTTP_GET, handleFileList);
  //load editor
  server.on("/edit", HTTP_GET, []() {
    if (!handleFileRead("/edit.htm")) {
      server.send(404, "text/plain", "FileNotFound");
    }
  });
  //create file
  server.on("/edit", HTTP_PUT, handleFileCreate);
  //delete file
  server.on("/edit", HTTP_DELETE, handleFileDelete);
  //first callback is called after the request has ended with all parsed arguments
  //second callback handles file uploads at that location
  server.on("/edit", HTTP_POST, []() {
    server.send(200, "text/plain", "");
  }, handleFileUpload);

  //called when the url is not defined here
  //use it to load content from FILESYSTEM
  server.onNotFound([]() {
    if (!handleFileRead(server.uri())) {
      server.send(404, "text/plain", "FileNotFound");
    }
  });

  //get heap status, analog input value and all GPIO statuses in one json call
  server.on("/all", HTTP_GET, []() {
    String json = "{";
    json += "\"heap\":" + String(ESP.getFreeHeap());
    json += ", \"analog\":" + String(analogRead(A0));
    json += ", \"gpio\":" + String((uint32_t)(0));
    json += "}";
    server.send(200, "text/json", json);
    json = String();
  });

  pinMode(LED,OUTPUT);
  digitalWrite(LED, LOW);
  portal.onDetect(startCP);

  if (portal.begin()) {
    digitalWrite(LED, LOW);
  }
  WiFi.setSleep(false);

  DBG_OUTPUT_PORT.println("HTTP server started");

  DBG_OUTPUT_PORT.println("");
  DBG_OUTPUT_PORT.print("Connected! IP address: ");
  DBG_OUTPUT_PORT.println(WiFi.localIP());

  MDNS.begin(host);
  DBG_OUTPUT_PORT.print("Open http://");
  DBG_OUTPUT_PORT.print(host);
  DBG_OUTPUT_PORT.println(".local/edit to see the file browser");

}

void loop(void) {
  portal.handleClient();
}
GeorgeFlorian commented 5 years ago

WiFi.setSleep(false); doesn't help !

CMGeorge commented 5 years ago

WiFi.setSleep(false); doesn't help !

D][WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128 [D][WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128 [D][WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128 [D][WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128

192.168.1.175 200 document Other 8.8 KB 136 ms
bootstrap.min.js (failed) script (index) 0 B 110 ms
bootstrap-table.min.css (failed) stylesheet (index) 0 B 99 ms
jquery-3.3.1.min.js 200 script (index) 85.0 KB 4.16 s
bootstrap-table.min.js (failed) script (index) 0 B 114 ms
bootstrap.min.css (failed) stylesheet (index) 0 B 106 ms
logo.png (failed)   (index) 0 B 4.14 s
favicon.ico 200 x-icon Other 1.2 KB 39 ms

All files exists, and works if I open them individually.

To check this, add to SPIFFS in /js this JS files, and to /css the css files Create a index html file and include them.

  <head>
    <meta name="viewport">
    <script src="/js/jquery-3.3.1.min.js"></script>
    <script src="/js/bootstrap.min.js"></script>
    <link rel="stylesheet" href="/css/bootstrap-table.min.css">
    <script src="/js/bootstrap-table.min.js"></script>
    <link href="/css/bootstrap.min.css" rel="stylesheet" title="main">
  </head>

not all src's are loaded. Accessing /js/FILENAME, everything works correctly tried adding file reference using:

server.serveStatic("/js", SPIFFS, "/js");
  server.serveStatic("/img", SPIFFS, "/img");
  server.serveStatic("/css", SPIFFS, "/css");

or

server.serveStatic("/js/bootstrap.min.js", SPIFFS, "/js/bootstrap.min.js");
  server.serveStatic("/js/bootstrap-table.min.js", SPIFFS, "/js/bootstrap-table.min.js");
  server.serveStatic("/js/jquery-3.3.1.min.js", SPIFFS, "/js/jquery-3.3.1.min.js");
  server.serveStatic("/css/bootstrap.min.css", SPIFFS, "/css/bootstrap.min.css");
  server.serveStatic("/css/bootstrap-table.min.css", SPIFFS, "/css/bootstrap-table.min.css");

index file is set for load as server.serveStatic("/", SPIFFS, "/web/index.html");

me21 commented 5 years ago

Since these files are loading all at the same time, you may be hitting SPIFFS max open files limit. I saw similar behavior in my project. Firefox re-requests the files in that case, so it only slowed down the page loading for me.

Try using Firefox if you're not already using it and see if it makes any difference.

CMGeorge commented 5 years ago

Since these files are loading all at the same time, you may be hitting SPIFFS max open files limit. I saw similar behavior in my project. Firefox re-requests the files in that case, so it only slowed down the page loading for me. Try using Firefox if you're not already using it and see if it makes any difference.

Interesting that my esp8266 is managing this situation without any problem.

MadDogMayCry0 commented 5 years ago

Same issue...

LucasFeliciano21 commented 5 years ago

Same problem here, but with the MQTT client, it just freezes and the Debug just shows "[D][WiFiClient.cpp:463] connected(): Disconnected: RES: 0, ERR: 128"

I think it's something related with the WifiClient.

Any news guys?

nae9 commented 5 years ago

WiFi.setSleep(false); after wifi.begin() help me eliminate appearing phantom client that block client parsing (with free buffer). Any way simple examples with wifi on ESP32 today get topic problem if not add WiFi.setSleep(false) in their setup. Probably this solving only masked initial cause of problem.

me21 commented 5 years ago

@nae9 can you please describe what exactly happens if you don't call WiFi.setSleep(false);?

nae9 commented 5 years ago

@nae9 can you please describe what exactly happens if you don't call WiFi.setSleep(false);?

See SimpleWiFiServer.ino example from WiFi examples branch: `void loop() { WiFiClient client = server.available(); // listen for incoming clients

if (client) { // if you get a client, Serial.println("New Client."); // print a message out the serial port while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); Serial.write(c); if (c == '\n') { // if the byte is a newline character if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); //... // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } //... } } // close the connection: client.stop(); Serial.println("Client Disconnected."); } } ` Normally when client connects, there is some message in buffer and you can read it by client.read() and this action decrement client.available() number by 1. After read last symbol (commonly = '\n') client.available()==0 and program jump from while (client.connected()) loop by break; and then client.stop(); zeroes client number. But on ESP32 release libs there is some bug... client.stop() not zeroing client number and in second loop we have client==1 but client.available() == 0 and program spin in infinity while loop. After some time timeout appeared and client disconnects by timeout, while loop ends and we see in debug console info about timeout:

... New Client. 17:53:51.764 -> GET / HTTP/1.1 17:53:51.764 -> Host: 192.168.1.210 17:53:51.764 -> User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0 17:53:51.764 -> Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 17:53:51.804 -> Accept-Language: en-US,en;q=0.5 17:53:51.804 -> Accept-Encoding: gzip, deflate 17:53:51.804 -> Connection: keep-alive 17:53:51.804 -> Upgrade-Insecure-Requests: 1 17:53:51.804 -> Client Disconnected. 17:53:51.884 -> New Client. [D][WiFiClient.cpp:452] connected(): Disconnected: RES: 0, ERR: 128 Client Disconnected.

If i type WiFi.setSleep(false); after WiFi.begin(), then client.stop() make client==0 and all work fine (as on other platforms). A couple year ago all work fine on ESP32 with no WiFi.setSleep(false); directive, but when WiFiClient was modified to use buffer somebody bugged...

atanisoft commented 5 years ago

This issue appears to go a bit deeper than just the sleep param. The read() method doesn't check if the client is still connected thus it may mask the disconnected state until some sort of timeout occurs. This may be a bug in the rxBuf code as it is only checking for bytes to read and not detecting the disconnected state until some timeout inside LwIP.

locchi93 commented 5 years ago

Same issue!

tfry-git commented 5 years ago

For what it's worth, a few things that I think I have understood about this problem, before hitting a wall:

  1. Error code 128 is ENOTCONN (socket is not connected).
  2. There appear to be two sources of the debug message. One is for connections that are simply closed by the remote. That one is quite benign.
  3. The other source of the message is when a new connection comes in, it sometimes isn't accepted, properly. That one is problematic.
  4. The closest I could get to the point of trouble was WiFiServer::available(). I inserted a check whether the newly created WiFiClient is actually connected(), inside this function. By this, I found that the error - if it occurs - occurs directly after the connection has been accepted.
  5. I toyed a bit with re-trying to accept the connection in this case, but if the error occurs, the same happens in the retries (only with different fd-numbers).
  6. Finally, I do seem to note that the problem is more likely to occur, when there are multiple incoming connections in close proximity (less than a second or so). When connections are more spaced out, things seem to run smoothly, for the most part. A race condition?

Not sure, whether this helps any. However at least it offers some insight into why setSleep(false) will help in some cases: As the error occurs when accepting connections, if you can avoid closing and re-opening connections, that will be a good thing. However, if you need to deal with a lot of short incoming connections, you're out of luck. Unfortunately, my use-case falls into the latter category...

paulhaggard commented 5 years ago

I'm seeing the same message with very similar circumstances as you guys, except it's not causing me any issues that I can see - I'm not trying to keep a websocket open. I have two clients connected, and they are able to interact with the http server I'm running.

I also appear to only see the message when log level is Debug or Verbose. Http headers look fine in Chrome inspector.

Are you all trying to have a websocket stay open?

tfry-git commented 5 years ago

@paulhaggard : Yes, the message is harmless in some case, but goes along with a real error in other cases.

TLDR: The error occurs, if the ESP is trying to accept a new client, while it has not yet finished writing. Testcase below.

I think I have finally narrowed down the conditions when this occurs. Hopefully, this will help in fixing this annoying issue. Below, you'll find a self-contained testcase. Amend setup() with your connection credentials, then point a browser at your ESP. Play with the parameters, and hit "Go" to send a series of AJAX requests. Long story short, for me the pattern is quite clear: If either the payload size (written by the ESP) is getting high, or, the timeout between requests is getting short, you'll start seeing errors. Near the tipping point, you'll see a distinct pattern of exactly every other request failing. For me the tipping point is around a payload size of 2500, and a delay of 500 ms, but YMMV depending on connection strength, etc.

So, in combination with what I've written earlier, I think we can conclude the problem is that accepting incoming connections is broken, while data has not yet finished writing.

Testcase:

#include <WebServer.h>
WebServer server(80);
void handlePage();

void setup() {
    Serial.begin (115200);
    Serial.setDebugOutput(true);

    // Example WIFI setup as an access point. Change this to your needs
    WiFi.mode(WIFI_STA);
    WiFi.begin("MyNet", "password");

    server.on("/", handlePage);
    server.begin();
}

void loop() {
    server.handleClient();
}

void handlePage() {
    server.setContentLength(CONTENT_LENGTH_UNKNOWN);
    if(server.method() == HTTP_POST) { // AJAX request
        int payload = server.arg("payload").toInt();
        Serial.print("Serving payload size: ");
        Serial.println(payload);
        server.send(200, "text/json", "");

        // spread the payload across a couple writes, for a more realistic API use
        for(int i = payload / 32; i > 0; --i) {
          server.sendContent("xxxxxxx.xxxxxxx.xxxxxxx.xxxxxxx.");
        }
        for(int i = payload % 32; i > 0; --i) {
          server.sendContent("x");
        }
    } else {  // Page load
        Serial.println("Serving test page");
        server.send(200, "text/html", "");
        server.sendContent(
"<!DOCTYPE html>\n"
"<html>\n"
"<body>\n"
"<h2>Connectivity test</h2>\n"
"\n"
"n <input type=\"text\" value=\"4\" id=\"n\"/>\n"
"payload <input type=\"text\" value=\"256\" id=\"payload\"/>\n"
"delay <input type=\"text\" value=\"1000\" id=\"delay\"/>\n"
"<button type=\"button\" onclick=\"document.getElementById('result').clear(); doTest(document.getElementById('n').value, document.getElementById('payload').value, document.getElementById('delay').value);\">Go</button>\n"
"\n"
"<h2>Result</h2>\n"
"<div id=\"result\">No test, yet</div>\n"
"\n"
"<script>\n"
"var results = document.getElementById('result');\n"
"result.update = function(sent, success, error, timeout) {\n"
"  this.innerHTML = 'Sent: ' + (this.sent += sent) + ' Successes: ' + (this.successes += success) + ' Errors: ' + (this.errors += error) + ' Timeouts: ' + (this.timeouts += timeout);\n"
"};\n"
"result.clear = function() {\n"
"  this.sent = this.successes = this.errors = this.timeouts = 0;\n"
"  this.update(0,0,0,0);\n"
"};\n"
"results.clear();\n"
"\n"
"function doTest(n, payload, delay) {\n"
"  if(n < 1) return;\n"
"  \n"
"  var req = new XMLHttpRequest();\n"
"  req.timeout = 5000;\n"
"  req.onload = function() { document.getElementById('result').update(0, (this.readyState == 4), 0, 0); };\n"
"  req.onerror = function() { document.getElementById('result').update(0, 0, 1, 0); };\n"
"  req.ontimeout = function() { document.getElementById('result').update(0, 0, 0, 1); };\n"
"  results.update(1, 0, 0, 0)\n"
"  req.open(\"POST\", \"/?payload=\" + payload, true);\n"
"  req.send(\"\");\n"
"  \n"
"  setTimeout(function() {doTest(n-1, payload, delay)}, delay);\n"
"}\n"
"</script>\n"
"</body>\n"
"</html>\n"
        );
    }
}
tfry-git commented 5 years ago

For what it's worth, I will add that the porting my test case to AsyncTCP / ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) makes the problem disappear.

So that might be both a workaround for the time being, and - hopefully - a hint towards a fix.

stale[bot] commented 5 years ago

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

tfry-git commented 5 years ago

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

I believe the reason that this report has not received any recent activity is not that it is no longer relevant. However, everything of relevance has already been stated. Please keep it open.

stale[bot] commented 5 years ago

[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.

tfry-git commented 5 years ago

No, dear stale bot, this still has not gone away.

stale[bot] commented 5 years ago

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

rudolf81 commented 5 years ago

For what it's worth, I will add that the porting my test case to AsyncTCP / ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer) makes the problem disappear.

So that might be both a workaround for the time being, and - hopefully - a hint towards a fix.

Yep, it does work, however you lose your second core when using ESPAsyncWebServer + AsyncTCP...

FilipeBecoAmador commented 4 years ago

I'm new to C++ so I'm probabily using pointers in the wrong way. I'm trying to create a library which has a server that uses multipleconnections of WiFiClients and I saved pointers to those clients in a vector. For some reason, when using pointers the connected() always returned the "Disconnected: RES: 0, ERR: 128" and if I used the objects themselves it worked. Hope this helps if you're getting the error. Also if you know what I'm doing wrong, please share it with me :)

lbernstone commented 4 years ago

Please do not hijack threads. If you have an problem, open a new issue and post some code.

stale[bot] commented 4 years ago

[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.

tfry-git commented 4 years ago

Bump.

Dear stale bot. I can see the point in closing issues if requested info isn't forthcoming. Closing issues just for lack of the addition of new noise seems rather lame to me.

stale[bot] commented 4 years ago

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

antonmeyer commented 4 years ago

maybe we should write a anti-stale-bot, running on an esp32

ElToberino commented 4 years ago

Really annoying that this still doesn't work properly. My server sends html files & a css file from SPIFFS and also some json data the browser calls via javascript functions - on page loading and/or triggered by user inputs on the website.

I face the issue - like some others obviously - that my code runs fine if the server calls are made with Firefox browser. Using a Chrome or Chromium based browser, the site and/or data loading stutters, partially fails or completely fails. This occurs on Windows and Android-> https://github.com/espressif/arduino-esp32/issues/3890

Btw: The same sketch runs fine with an ESP8266 with FF AND Chrome.

surfsoft commented 4 years ago

Same issue over here. I'm porting a framework I developed on the ESP8266 over to the ESP32 and WebServer is unable to handle overlapping HTTP requests in the way that the ESP8266WebServer class could. It's a real blocker.

surfsoft commented 4 years ago

And WiFi.setSleep(false); is of no help but as has been already said, that's at best a work-around. If I have time I will try and dig in a bit more to see what is going on.

tfry-git commented 4 years ago

And WiFi.setSleep(false); is of no help but as has been already said, that's at best a work-around. If I have time I will try and dig in a bit more to see what is going on.

At the danger of spamming in an already long issue thread: I think I have made some progress tracking down, when this happens (unfortunately, I did not find out, why this happens). And at any rate, I have a self contained test-case that should help in any effort to nail down the problem. See both at: https://github.com/espressif/arduino-esp32/issues/1921#issuecomment-471927946

rudolf81 commented 4 years ago

I've been experimenting a bit further- and I found the ESP32 HTTPS Server library.

This Web Server is quite good and supports a lot of extras including HTTPS and web sockets.

As I mentioned in my comment above, a common "solution" for this concurrent request connection dropped issue is to make use of the AsyncTCP & ESPAsyncWebServer library combo and port your web code over to this framework... It works well, however due to how this libraries works - you lose exclusive access to the second core of the ESP32. While this might not be a big deal to some, if you have some time critical code in your application, which needs to run on a different core, this is not a solution.

Compared to the ESP32 HTTPS Server library, which is about a 1/3 in size compared to AsyncTCP + ESPAsyncWebServer, I was surprised to see it can work on the primary core only, and does not suffer from the concurrent request connection dropped issue at all!

So - if you are reading this and you are looking for a more lightweight or single-cored option then give ESP32 HTTPS Server library a go. You will still have to port your web code over.

I wrote a test sketch (ESP32 Web Server test cases for concurrent connection issue.zip) to tests the "ESP32 HTTPS Server" library as a solution to the concurrent request dropped connection problem affecting the default EPS32 platform WebServer class which is loaded from "\esp32\hardware\esp32\1.0.4\libraries\WebServer\".

Specifically - this test verifies that ESP32 HTTPS Server is able to serve concurrent web requests without dropping connections, AND not make use of the second core of the ESP32.

This sketch creates a simple web server instance from ESP32 HTTPS Server, adds three request handlers to load simple json data for ajax requests, and connects the FS to load the index.html page. The index.html page will make 3 concurrent ajax requests for json data and update the DOM with the results.

To ensure that ESP32 HTTPS Server does not make full or partial use of the second core of the ESP32, this sketch creates a pinned process on the second core. This runs in a hot loop with no yield or delay. Printout from this loop will be visible in the serial monitor. (This same method will not work with the ESPAsyncWebServer + AsyncTCP combo, and the pinned process will not execute)

That zip file also contains a control test for the base framework WebServer class which demonstrates the dropped connection problem...

This gives me hope! - it demonstrates that the concurrent requests are indeed possible on the ESP32 without needing to go down all the way to asyn tcp. I'm confident that the base WebServer class in the 1.04 framework can indeed be fixed, however I have little confidence that Espressif will ever fix this issue.

They are waiting for someone from the community to step up and do this...

If you are reading this - just bite the bullet now, port your code to a new lib, and live with the fact that your code will not be backwards compatible with ESP8266.

surfsoft commented 4 years ago

That's a really helpful post @rudolf81 - I will certainly take a look. I'm porting my ESP8266 framework on a branch of my original Github project, so backward compatibility isn't a big issue. Much as I like the ESP8266 it has too little RAM to do everything I'd like it to.

Update: Started a trial port but had to stop. Unfortunately there's no way to bind class methods as resource request handlers. Normally I'd bind a class method using a variation of

std::bind(&MyClass::myMethod, this, std::placeholders::_1, std::placeholders::_2))

But the library declares and uses a typedef that stops this technique from working.

cyberman54 commented 4 years ago

i ran in same issue, looking for a solution. Any news here?

olixr commented 4 years ago

Bump. I also am working with some libraries that made use of Wifi and WiFiServer. On the ESP8266 it works fine but switching to ESP32 I am having this disconnection problem. When trying to make multiple connections with short delays in between the error occurs. When I made use of flush() I would get a Guru panic error.

stale[bot] commented 4 years ago

[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.

tfry-git commented 4 years ago

Thank you for your noise, stalebot.

stale[bot] commented 4 years ago

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

olixr commented 4 years ago

Is there any news on this?

xreef commented 4 years ago

Hi any news? any fix?

cyberman54 commented 4 years ago

also still fighting this issue

xreef commented 4 years ago

With esp8266 (ESP8266WebServer) work without problems

xreef commented 4 years ago

Also here #3444