problem with http server

Hi,
I am having a problem with the simple http server, on an esp32. It is running into long wait times or finally a timeout while waiting for the request line in *client.readStringUntil('\r') . *
When I call the page from a browser, the first request mostly runs flawlessly: client connects and the request line is received within very short time and it sends out the page. But then direcly after, the client is still connected and no request line is delivered so that the timeout expires and my program is blocked for a few secs. When favicon is requested, it is handled fast.
The prominent problem is, that the page calls and answeres always become interleaved. The server waits for the request line of a first call, but only when the page is called again, (I use an automatic refresh every 1 sec) this request line frees the process to proceed. For me it looks like a bug in the implementation of these http server functions. I'd love to use asynchronuous server functions, but I don't have implemented that yet.

This is a stripped down example without an automatic refresh of the page. You have to type the IP adress of your module into the address bar to call the page, and probably reload often. On the delivered page it shows how long it took to receive the request.

#include       <WiFi.h>       // for ESP32
//#include <ESP8266WiFi.h>        //für esp8266


char        chBuffer[128];                                  // general purpose character buffer
const char      chPassword[] = "xxxxxx";               // your network password
const char      chSSID[] =     "yyyyyy";                   // your network SSID
const char* NTPStr = "192.168.178.1";    // specify NTP IP


WiFiServer httpserver(80);




//--------------------------------------------------------------------------------------------
void httpserverfnct() {


  WiFiClient client = httpserver.available();  //wir bekommen einen client der Daten zum Empfangen bereit hat  server.avail liefert client
  if (!client) {
    return;     //raus
  } //kein client


  //client ist verbunden, aber oft kein http request vorliegend
  int bytesatstart = client.available();   //wieviele bytes des http requests sind verfügbar?  Ausgabe unten über page
  Serial.println(F("ein client ist da"));   // hier meist noch keine bytes avail, nur ganz am Anfang


  client.setTimeout(2); // Sekunden beis ESP32!!!  gehört zu client.readStringUntil(), Daten immer nur von nächstem Aufruf?
  //  client.setTimeout(1500); //Millisekunden bei ESP8266!!!


  // Read the first line of the request
  unsigned long t1 = millis();                //wie lang dauert es bis request line kommt?
  String req = client.readStringUntil('\r');  // i.A. GET / HTTP/1.1   nächste bytes 10  72  chr(10)=\n, chr(13)=\r, meist 1050ms Wartezeit,
  //alles um einen Abruf verschoben? am ende client noch da aber keine Daten kommen mehr
  //client.stop wenn timeout?
  unsigned long timeto1stline = millis() - t1; //wie lang dauert es bis request line kommt?
  Serial.print(F("Wartezeit: "));
  Serial.println(timeto1stline);              //Ausgabe auch über http Seite


  Serial.print(F("first request line: "));
  Serial.println(req);




  bool reqok = ((req.indexOf(F("favicon")) == -1) && (req.indexOf(F("GET /")) != -1));


  while (client.available()) {        //client.avail liefert anzahl bytes     
    client.read();
  }  //request weglesen  mehrere Zeilen


  time_t tn = time(nullptr);     //Uhrzeit für page
  struct tm * tmPointer = localtime(&tn);     //  struct tm timeinfo;
  strftime (chBuffer, sizeof(chBuffer), "%a, %d %b %Y %H:%M:%S",  tmPointer);   //formatierte Zeitangabe in chbuffer aus Einzelzahlen in &tmpointer


  if  (reqok) {         
    Serial.println(F("war ein HTTP req, page gesendet"));


    client.print(F("HTTP/1.1 200 OK\r\n Content-Type: text/html\r\n\r\n"));


    client.print(F("<!DOCTYPE html> <html> <head> <title>HTTP Polling Test</title></head> "));


    client.print(F("<body><table style=\"width: 70%; margin-left: auto; margin-right: auto;\"><tbody style=\"text-align: center;\">"));


    client.print(F("<tr><td>Bytes bei Verbindg vorliegend</td> <td>ms Zeit bis http request geliefert</td></tr>"));
    client.print(F("<tr><td><h1><span style=\"color: #0000ff;\"> "));
    client.print(bytesatstart);
    client.print(F("</span></h1></td> <td><h1><span style=\"color: #0000ff;\"> "));
    client.print(timeto1stline);
    client.print(F("</span></h1></td></tr>"));
    client.print(F("<tr><td>&nbsp;</td> <td>&nbsp;</td></tr>"));    //leerzeile


    client.print(F("<tr><td style=\"text-align: center;\" colspan=\"2\">Request line</td></tr>"));
    client.print(F("<tr><td style=\"text-align: center;\" colspan=\"2\"><h1><span style=\"color: #0000ff;\"> "));
    client.print(req);
    client.print(F("</span></h1></td></tr>"));




    client.print(F("<tr><td style=\"text-align: center;\" colspan=\"2\">Zeit/Datum</td></tr>"));
    client.print(F("<tr><td style=\"text-align: center;\" colspan=\"2\"><h1><span style=\"color: #0000ff;\"> "));
    client.print(chBuffer);
    client.print(F("</span></h1></td></tr>"));


    client.print(F("</tbody></table></body></html> "));


  }  //GET HTTP
  else {
    Serial.println(F("war kein HTTP req"));     //favicon wird nur 1x abgefragt
    client.print(F("HTTP/1.1 404 Not Found"));
  }


  client.flush();                   // Waits until all outgoing characters in buffer have been sent.
  if (!client.connected()) {
    client.stop();
    Serial.println(F("ciao"));
  }   //client gegangen
}  //httpservfnct
//--------------------------------------------------------------------------------------------
void setup() {


  Serial.begin(115200);
  while (!Serial)
  {  }     //warten


  Serial.println("connecting WiFi");   //stat auf serial
  WiFi.begin(chSSID, chPassword);
  while (WiFi.status() != WL_CONNECTED)
  {
    Serial.print(".");
    delay(200);
  }
  Serial.println();
  Serial.printf("WiFi connected to %s \r\n", chSSID);   //stat auf serial


  //configTime("CET-1CEST,M3.5.0/02,M10.5.0/03", NTPStr);   //"de.pool.ntp.org"   esp8266
  configTime(0, 0, NTPStr);                            // esp32
  setenv("TZ", "CET-1CEST,M3.5.0/02,M10.5.0/03" , 1);  // esp32


  char  chIp[81];
  WiFi.localIP().toString().toCharArray(chIp, sizeof(chIp) - 1);
  Serial.printf("eigene IP  : %s \r\n", chIp);


  httpserver.begin();
  Serial.println(F("http Server started"));


}   //setup end


//-----------------------------------------------------------------------------------------
void  loop() {


  httpserverfnct();   //jedes mal nachschauen
}  //loop

See my Arduino Software Solutions for non-blocking ways to read Strings and stop at the terminator.
Also includes non-blocking timeouts

use the WebServer library of esp32 Arduino boards support package

You can alter the timeout of readStringUntil('\r')
See: Stream.setTimeout() - Arduino Reference
However, unless you are sure everything is terminated as you expect, it probably better to find another method of doing this.
Writing your own web server, if that is what you are doing, will certainly be an educational experience.

Edit:

I've just noticed that you are already setting the timeout anyway.

An HTTP GET request will have multiple '\r' characters, for example:
from Using Arduino IDE | Adafruit HUZZAH ESP8266 breakout | Adafruit Learning System

  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  delay(500);

Your code has to swallow all that without a series of pauses.

I tried with an esp8266 board and it behaves like the esp32. Oftenly a client appears, but no request line is received. To receive the page in the browser I have to do a reload very short after the first call, then the second request comes through.
Most of the times the client connects again after a page has been sent, but again no request.
I tried to send a client.stop after every transmission or fail, but it did'nt change anything.
with a very short timeout I can avoid a long blocking time, but again, requests come in unrelyably.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.