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);
}