Webclient - Antwort auswerten

Ich bin gerade dabei, ein programm zu schreiben, dass mir die öffentliches IPs aller meiner Gateways ermittelt und weiterschickt.
Insgesamt habe ich 4 Gateways. Ich frage nacheinander auf checkip.dyndns.com an und bekomme eine Antwort, in der die IP enthalten ist.
Nun beginnt das Problem. Ich finde keinen gescheiten Client Code, der mir vernünftig die Antwort in einen Buffer schreibt, ohne das System zu lange zu blockieren (while Schleife, oder delay, warum auch immer.

Folgender Code läuft recht zufriedenstellend, aber oft habe ich connection failed bzw. einen Timeout, weil eben der Server nicht antwortet (vielleicht hat er die Anfrage gar nicht bekommen?). Es sind auch immer verschiedene Gateways wenn keine Antwort kommt.

Mache ich die Tests mit "blockierendem Code, sind die Fehler nahezu null. Deswegen gehe ich davon aus, dass es am Programm liegt und nicht an der Verfügbarkeit der Gateways. Zum Testen kann man auch 4 Mal das gleiche Gateway eintragen, da ja die wenigsten 4 Internetzugänge zu Hause haben.

#include <SPI.h>
#include <Ethernet.h>
#include <Streaming.h>
#include <PString.h>
#include <utility/w5100.h>

// Netzwerkparameter
uint8_t mac[6] = {
  0x74,0x69,0x69,0x2D,0x30,0x31};
byte gateway[][4] = { 
  { 
    172, 26, 0, 01   } 
  , { 
    172, 26, 0, 02   } 
  , { 
    172, 26, 0, 20   } 
  , { 
    172, 26, 0, 21   } 
};                
byte ips[]  = { 
  172, 26, 0, 161   };  
byte dnstest[] = { 
  80, 58, 61, 250   };
byte subnet[]  = { 
  255, 255, 255, 0   };
EthernetClient client;  

char linebuf[71];
char buffer1[17];
char buffer2[100];   //ziel für leerzeichen ersetzen
char ipbuf[17];
PString IP(ipbuf, sizeof(ipbuf));
char* error[] = {
  "ok", "----Client connect failed", "------------timeout"};
byte errorcode;
byte debug=0;


void setup() {
  Serial.begin(9600);
  digitalWrite(2, HIGH);
  delay(1000);
}

void loop() {

  for (int z=0;z<4;z++){      // die 4 GW durchgehen



    Serial << "GW " << z << " initialisieren, " ;
    for (int y=0;y<4;y++)
    {
      Serial<<(gateway[z][y]);
      if (y<3) Serial << ".";
    }
    
     serverAbfrage(gateway[z]);
     Serial << "  " << IP << " gefunden.  Code: "  ;
     Serial << error[errorcode] << endl; 
     


    delay(200);
  }
  Serial<<endl;
 


}

void serverAbfrage(byte* gateway)
//char* serverAbfrage(byte* gateway)
{ 
  char buffer[300];  
  PString webg(buffer, sizeof(buffer));
  unsigned long next;
  errorcode=0;


  Ethernet.begin(mac,ips,dnstest,gateway,subnet);  //mac,ips,dnstest,gateway,subnet
  W5100.setRetransmissionTime(20000);    // Timeout 2 sec
  W5100.setRetransmissionCount(3);       // 3 Versuche

  delay(100);
  //    Serial.print("gatewayIP: ");  
  //    Serial.print(Ethernet.gatewayIP());
  if (((signed long)(millis() - next)) > 0)  //solange die 5 sec. noch nicht rum sind, wird die if ausgeführt
  {
    next = millis() + 5000;
    if (debug) Serial.println("Client connect");
    if (client.connect("checkip.dyndns.com",80))
    {
      delay(100); 
      if (debug)     Serial.println("Client connected");
      client << F("GET / HTTP/1.1\n\rHost: checkip.dyndns.com\n\rUser-Agent: arduino-ethernet\n\rConnection: close")<<endl<<endl;
      if (debug)     Serial.println("String abgeschickt");
      while(client.available()==0) // wenn client nicht mehr verfügbar und 5 sec rum, -> schliessen
      {
        if (debug)  Serial << ((signed long)(next - millis())) << " next - millis()    " << next << "  next     " << millis() << " millis" << endl; 
        if ((signed long)(next - millis()) < 0)
        {
          if (debug)   Serial.println("Goto close, Zeit abgelaufen");
          errorcode=2; 
          goto close;

        }
      }
      if (debug) Serial.println("Size initialisieren");  
      int size;
      while((size = client.available()) > 0)
      {
        uint8_t* msg = (uint8_t*)malloc(size);
        size = client.read(msg,size);

        for( int i = 0; i < sizeof(buffer);  ++i )    buffer[i] = (char)0;   // buffer löschen
        webg="";
        for (int x=0; x<=size-1; x++)
        {
          webg.write( msg[x]) ;

        }
        if (debug) Serial << "size=" << size << endl;
        
        IP = suche(buffer, "ss: ", "</body>");
        free(msg);

      }
close:

      if (debug) Serial.println("Client stopps now");
      client.stop();
      if (debug) Serial.println("Client stopped");

    }
    else
    {
      if (debug) Serial.println("Client connect failed");
      errorcode=1;
    }
  }
  next=0; 
  if (errorcode) IP="0.0.0.0"; 
  else errorcode=0;
  return; //  (ipbuf);    
}

char* suche(char *string, char *vor_suchstring, char *nach_suchstring)  // gibt als Ergebnis den Inhalt zwischen den beiden Suchstrings
{
  for( int i = 0; i < sizeof(buffer1);  ++i )    buffer1[i] = (char)0;   // buffer löschen
  char *c=strstr(string, vor_suchstring)+strlen(vor_suchstring);
  char *d=strstr(string, nach_suchstring);
  strncpy(buffer1, linebuf+(c-linebuf), (d-linebuf)-(c-linebuf));
  //Serial << "Buffer1 ist " << strlen(buffer1) << " Zeichen lang und enthaelt: " << buffer1 << endl;
  return(buffer1);  
}

char* leerErsetzen(char* text)
{
  int leseZeiger = 0;
  int schreibZeiger = 0;

  for(leseZeiger = 0; leseZeiger<=strlen(text);leseZeiger++)
  { 
    if (text[leseZeiger] != 0x20) 
    {  
      buffer2[schreibZeiger++]=text[leseZeiger];
    }  
    else
    {                         
      buffer2[schreibZeiger++] = '%';
      buffer2[schreibZeiger++] = '2';
      buffer2[schreibZeiger++] = '0';
    } 
  } 
  schreibZeiger++;
  buffer2[schreibZeiger] = '\n';
  return(buffer2);
}

Ich bekomme dann so eine Ausgabe:

GW 0 initialisieren, 172.26.0.1  95.21.203.24 gefunden. Dauer: 1231  Code: ok
GW 1 initialisieren, 172.26.0.2  0.0.0.0 gefunden. Dauer: 14605  Code: ----Client connect failed
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 1425  Code: ok
GW 3 initialisieren, 172.26.0.21  0.0.0.0 gefunden. Dauer: 10886  Code: ------------timeout

GW 0 initialisieren, 172.26.0.1  0.0.0.0 gefunden. Dauer: 7359  Code: ------------timeout
GW 1 initialisieren, 172.26.0.2  0.0.0.0 gefunden. Dauer: 11389  Code: ------------timeout
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 1416  Code: ok
GW 3 initialisieren, 172.26.0.21  0.0.0.0 gefunden. Dauer: 6402  Code: ------------timeout

GW 0 initialisieren, 172.26.0.1  95.21.203.24 gefunden. Dauer: 1357  Code: ok
GW 1 initialisieren, 172.26.0.2  77.229.88.249 gefunden. Dauer: 1068  Code: ok
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 958  Code: ok
GW 3 initialisieren, 172.26.0.21  79.145.88.54 gefunden. Dauer: 1456  Code: ok

GW 0 initialisieren, 172.26.0.1  95.21.203.24 gefunden. Dauer: 1225  Code: ok
GW 1 initialisieren, 172.26.0.2  77.229.88.249 gefunden. Dauer: 1473  Code: ok
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 1063  Code: ok
GW 3 initialisieren, 172.26.0.21  0.0.0.0 gefunden. Dauer: 7745  Code: ------------timeout

GW 0 initialisieren, 172.26.0.1  95.21.203.24 gefunden. Dauer: 1155  Code: ok
GW 1 initialisieren, 172.26.0.2  77.229.88.249 gefunden. Dauer: 1487  Code: ok
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 1422  Code: ok
GW 3 initialisieren, 172.26.0.21  79.145.88.54 gefunden. Dauer: 1345  Code: ok

GW 0 initialisieren, 172.26.0.1  0.0.0.0 gefunden. Dauer: 14659  Code: ----Client connect failed
GW 1 initialisieren, 172.26.0.2  77.229.88.249 gefunden. Dauer: 1056  Code: ok
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 971  Code: ok
GW 3 initialisieren, 172.26.0.21  79.145.88.54 gefunden. Dauer: 1194  Code: ok

GW 0 initialisieren, 172.26.0.1  95.21.203.24 gefunden. Dauer: 1209  Code: ok
GW 1 initialisieren, 172.26.0.2  77.229.88.249 gefunden. Dauer: 2058  Code: ok
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 1065  Code: ok
GW 3 initialisieren, 172.26.0.21  79.145.88.54 gefunden. Dauer: 1189  Code: ok

GW 0 initialisieren, 172.26.0.1  95.21.203.24 gefunden. Dauer: 1325  Code: ok
GW 1 initialisieren, 172.26.0.2  77.229.88.249 gefunden. Dauer: 1495  Code: ok
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 1443  Code: ok
GW 3 initialisieren, 172.26.0.21  79.145.88.54 gefunden. Dauer: 1344  Code: ok

GW 0 initialisieren, 172.26.0.1  0.0.0.0 gefunden. Dauer: 5505  Code: ------------timeout
GW 1 initialisieren, 172.26.0.2  77.229.88.249 gefunden. Dauer: 2020  Code: ok
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 958  Code: ok
GW 3 initialisieren, 172.26.0.21  79.145.88.54 gefunden. Dauer: 1199  Code: ok

GW 0 initialisieren, 172.26.0.1  0.0.0.0 gefunden. Dauer: 14611  Code: ----Client connect failed
GW 1 initialisieren, 172.26.0.2  0.0.0.0 gefunden. Dauer: 11832  Code: ------------timeout
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 966  Code: ok
GW 3 initialisieren, 172.26.0.21  79.145.88.54 gefunden. Dauer: 1207  Code: ok

GW 0 initialisieren, 172.26.0.1  95.21.203.24 gefunden. Dauer: 1247  Code: ok
GW 1 initialisieren, 172.26.0.2  0.0.0.0 gefunden. Dauer: 11167  Code: ------------timeout
GW 2 initialisieren, 172.26.0.20  77.225.81.63 gefunden. Dauer: 961  Code: ok
GW 3 initialisieren, 172.26.0.21

Ich verwende fast den Standart Code der so ausschaut:

Der funktionert zufriedenstellend, halt nur mit einem Gateway

EthernetClient client = server.available();

  if (client) {
    
    //Serial.println("new client");

    // an http request ends with a blank line
 boolean currentLineIsBlank = true;
    while (client.connected()) {
            if (client.available()) {
                      char c = client.read();
      
            html_reponse[html_counter]=c;
             html_counter++;
                if (html_counter>=MAX_RESPONSE_CHARS) break;

        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
if (c == '\n' && currentLineIsBlank) {
                      
                    //Antworte dem Browser
                       Serial.print(html_reponse);
      

                           }


 if (c == '\n') {
         

          currentLineIsBlank = true;
                 }

        else if (c != '\r') {
          // you've gotten a character on the current line
           currentLineIsBlank = false;
                             }


      }
    }
    // give the web browser time to receive the data
    delay(1);
        
    // close the connection:
    client.stop();
    //Serial.println("client disonnected");
   
       html_counter=0;
  }

Das ist doch Code für Arduino als Server, der Clientanfragen beantwortet.

Ich will es ja gerade andersrum. Ich stelle eine Anfrage an einen Server (checkip.dyndns.com) und will die Antwort (darin ist die gesuchte IP) auswerten.

Und eben diese Antwort kommt manches mal nicht oder der Arduino will sie nicht enpfangen. Nun weiss ich eben nicht, ob es an meinem Code liegt oder am Internet generell. Und meinen Code möchte ich noch dahingehend optimieren, dass er die übrigen Ablaufe nicht unnötig aufhält.

ElEspanol:
Das ist doch Code für Arduino als Server, der Clientanfragen beantwortet.

Oh sorry, ja :-* War nicht aufmerksam.