Webserver wertet nicht aus - warum ??

Hallo,

ich probiere gerade ein wenig im Bereich Webserver und habe folgenden Sketch (zugegeben, teilweise aus Internet-Fundstücken zusammengesetzt):

// #include <SPI.h>        // ENC28J60 Ethernet
#include <UIPEthernet.h>   // ENC28J60 Ethernet

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 200); 
EthernetServer server(80);

String HTTP_req;          // stores the HTTP request
boolean LED_status = 0;   // state of LED, off by default

void setup()
{
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin();           // start to listen for clients
    Serial.begin(9600);       // for diagnostics
    pinMode(3, OUTPUT);       // LED on pin 3
    pinMode(4, OUTPUT);       // LED on pin 4
}

void loop()
{
    EthernetClient client = server.available();  // try to get client

    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                HTTP_req += c;  // save the HTTP request 1 char at a time
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println(F("HTTP/1.1 200 OK"));
                    client.println(F("Content-Type: text/html"));
                    client.println(F("Connection: close"));
                    client.println();
                    // send web page
                    client.println(F("<!DOCTYPE html>"));
                    client.println(F("<html>"));
                    client.println(F("<head>"));
                    client.println(F("<title>Arduino LED Control</title>"));
                    client.println(F("</head>"));
                    client.println(F("<body>"));
                    client.println(F("<h1>Christian's Webserver</h1>"));
                
                    client.println(F("<form method=get>"));
                    client.println(F("
Ausgang A <input type=submit name=a value=ein><input type=submit name=a value=aus>"));
                    client.println(F("
Ausgang B <input type=submit name=b value=ein><input type=submit name=b value=aus>"));
                    client.println(F("</from>"));
                    
                    client.println(F("

"));
                    
                    client.println(F("<p>Analog Eingang:</p>"));
                    for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
                       int sensorReading = analogRead(analogChannel);
                       client.print(F("Analog Eingang "));
                       client.print(analogChannel);
                       client.print(F(" : "));
                       client.print(sensorReading);
                       client.println(F("
"));      
                    }
                    
                    client.println(F("</body>"));
                    client.println(F("</html>"));
                    Serial.println(HTTP_req);
                    
                    if (HTTP_req.indexOf("GET /?a=ein")>0){
                      digitalWrite (3, HIGH);
                      Serial.println(F("Pin 3 Ein"));
                    }
                    if (HTTP_req.indexOf("GET /?a=aus")>0){
                      digitalWrite (3, LOW);
                      Serial.println(F("Pin 3 Aus"));
                    }
                    if (HTTP_req.indexOf("GET /?b=ein")>0){
                      digitalWrite (4, HIGH);
                      Serial.println(F("Pin 4 Ein"));
                    }
                    if (HTTP_req.indexOf("GET /?b=aus")>0){
                      digitalWrite (4, LOW);
                      Serial.println(F("Pin 4 Aus"));
                    }  
                                        
                    HTTP_req = "";    // finished with request, empty string
                    break;
                }
                // every line of text received from the client ends with \r\n
                if (c == '\n') {
                    // last character on line of received text
                    // starting new line with next character read
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    // a text character was received from client
                    currentLineIsBlank = false;
                }
            } // end if (client.available())
        } // end while (client.connected())
        delay(1);      // give the web browser time to receive the data
        client.stop(); // close the connection
    } // end if (client)
}

Prinzipiell läuft das, nur die Ausgänge schalten nicht (Zeile 69, 74, 77, 81).
Es sieht so aus als ob if (HTTP_req.indexOf("GET /?a=ein")>0) nicht wahr ist obwohl im HTTP_req String z.B. das GET /?a=ein enthalten ist.
Andere "fertige" Beispiele die auch mit index.Of arbeiten laufen aber problemlos.

Bitte, kann jemand einen Blick auf meinen Code werfen, ich übersehe wahrscheinlich ein Detail.

Christian

=0

Hallo,

vielen Dank, damit geht es zumindest mit dem PC (Firefox). Aber mit dem Android Handy schaltet er der Reihe nach beide Ausgänge ein und sofort wieder aus. :drooling_face:
Was auffällt ist das der HTTP Request String vom Handy aus viel länger ist als vom PC. Kann es sein daß ich da schon ans Ende vom RAM komme? Ich gehe mal von max. 600byte (Laut Autor) für die Ethernet Lib aus, und abgesehen von dem einen Sting hab ich nicht so viel im Speicher, oder übersehe ich etwas.

Serieller Monitor mit PC-Firefox:

GET /?a=ein HTTP/1.1
Host: 192.168.0.200
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:28.0) Gecko/20100101 Firefox/28.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.0.200/?a=aus
Connection: keep-alive


Pin 3 Ein
GET /?a=aus HTTP/1.1
Host: 192.168.0.200
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:28.0) Gecko/20100101 Firefox/28.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://192.168.0.200/?a=ein
Connection: keep-alive


Pin 3 Aus

Serieller Monitor mit Android Browser:

GET /?a=ein HTTP/1.1
Host: 192.168.0.200
Connection: keep-alive
Referer: http://192.168.0.200/?a=ein
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
X-Requested-With: com.android.browser
User-Agent: Mozilla/5.0 (Linux; U; Android 4.1.1; de-at; SonyC1505 Build/11.3.A.2.23) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Accept-Encoding: gzip,deflate
Accept-Language: de-AT, en-US;q=0.8
Accept-Charset: utf-8, iso-8859-1, utf-16, *;q=0.7
x-wap-profile: http://uaprof.sonymobile.com/C1505R402.xml
x-GETzip: supported
Cache-Control: no-cache


Pin 3 Ein
Pin 3 Aus
Pin 4 Ein
Pin 4 Aus
GET /?a=aus HTTP/1.1
Host: 192.168.0.200
Connection: keep-alive
Referer: http://192.168.0.200/?a=ein
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
X-Requested-With: com.android.browser
User-Agent: Mozilla/5.0 (Linux; U; Android 4.1.1; de-at; SonyC1505 Build/11.3.A.2.23) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Accept-Encoding: gzip,deflate
Accept-Language: de-AT, en-US;q=0.8
Accept-Charset: utf-8, iso-8859-1, utf-16, *;q=0.7
x-wap-profile: http://uaprof.sonymobile.com/C1505R402.xml
x-GETzip: supported
Cache-Control: no-cache


Pin 3 Ein
Pin 3 Aus
Pin 4 Ein
Pin 4 Aus

Wie könnte ich den String in der Länge begrenzen (wirklich interessant sind ja eigentlich nur die ersten paar Zeichen) ohne daß die Erkennung des vollständigen HTTP Request unsicher wird?

Christian

Als "würgaround" den Index den indexOf findet nach oben hin begrenzen.
Und dies in der If Abfrage als && Bedingung einbauen.

Wobei auch beim Android Request z.b das "GET /?a=aus" auch nur einmal vorkommt :blush:
Deshalb wird meine Idee nicht zielführend sein, und es wird wohl doch das Sram aufgefressen.

Du könntest hier die Zeichen zählen HTTP_req += c; und ein maximum definieren und dann keine weitere Zeichen einlesen.

Ich würde aber das String Objekt nicht nutzen, ein Char Array funktioniert hier besser und sauberer.

Hallo,

rudirabbit:
Du könntest hier die Zeichen zählen HTTP_req += c; und ein maximum definieren und dann keine weitere Zeichen einlesen.

Das scheint zu funktionieren, vielen Dank. Ist wohl wirklich das RAM...

rudirabbit:
Ich würde aber das String Objekt nicht nutzen, ein Char Array funktioniert hier besser und sauberer.

Hmm, warum? Nur weil es eine feste Größe und damit in Bezug auf RAM berechenbarer ist oder gibt es andere
Gründe.

Christian

Die String Klasse ist ganz, ganz großer Murks. Verbraucht viel Speicher, ist langsam und noch dazu extrem stark in ihrem Funktionsumfang eingeschränkt.

Wenn man zwei Strings zusammenfügt ist es am schlimmsten, weil dann ein String davon zerstört wird und der andere vergrößert werden muss. Ich habe mal nachgeschaut. Es wird realloc() gemacht. Also ein String bleibt erhalten. Das kostet aber auch Zeit.
Wenn man immer einen char anhängt, muss der String auch ständig größer gemacht werden. Auf einem PC ist das ok, solange man es nicht extrem oft macht. Auf einem µC mit begrenztem RAM ist das Irrsinn. Und er macht den String jedesmal nur um 1 größer. Das ist nicht schön. Ein Vektor sollte idealerweise so implementiert sein, dass er stärker wächst, je öfter er wachsen muss.

Wenn man mehrere Strings im Programm hat und macht mal den und mal den größer fragmentiert man sich so letztendlich den Heap.

Du solltest wenigstens reserve() verwenden, damit das Array im Hintergrund erst mal mehr Speicher hat und nicht ständig erweitert werden muss:

Damit kann man den String auf z.B. 200 Zeichen initalisieren und es wird nicht ständig realloc() gemacht