Forum: Mikrocontroller und Digitale Elektronik ESP8266 als TCP Server verschluckt Client Pakets


von Georg W. (gewe)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe folgenden Aufbau:

PC mit C# Anwendung welche im 1 Sekundentakt als TCP Client eine 
Verbindung zum ESP aufbaut, 4 Bytes an einen ESP8266 sendet und die 
Verbindung abbaut.

Der ESP8266 wird mit der Arduino IDE programmiert. Boadrdefinitionen und 
Bibliotheken sind aktuell.

Ich habe das Beispiel von Stefan Frings versucht auf eine feste 
Kommandolänge von 4 Bytes umzustellen.

http://stefanfrings.de/esp8266/#atserver

Der komplette Sketch ist im Anhang.

Die geänderte Funktion sieht so aus:
1
bool getCommand(Stream& source, char* buffer, int bufSize, char maxLength)
2
{
3
    int data=source.read();
4
    if (data>=0)
5
    {
6
        int len=static_cast<int>(0);
7
        do
8
        {
9
            #ifdef DEBUG
10
            if (len==0)
11
            {
12
              Serial.println(F(""));
13
              Serial.print(F("Packet started: "));
14
              PaketCount++;
15
              Serial.println(PacketCount);
16
            }
17
            #endif
18
          
19
            if (len<bufSize-1)
20
            {
21
                buffer[len++]=static_cast<char>(data);
22
            }
23
            if (len==maxLength)
24
            {
25
                buffer[len]='\0';
26
                len=0;
27
                #ifdef DEBUG
28
                Serial.println(F("Packet done"));
29
                #endif
30
                return true;
31
            }
32
            data=source.read();
33
        }
34
        while (data>=0);
35
        buffer[len]='\0';  
36
    }
37
    return false;
38
}

Was jetzt passiert ist folgendes:

Obwohl ich im Wireshark sehe, dass die Pakete der C# Anwendung rausgehen 
und vom ESP8266 auch quittiert werden, springt die Empfangsroutine 
sporadisch nicht an. Das Problem tritt ca. einmal pro 10 Übertragungen 
auf. Jedoch konnte ich keine Muster erkennen, wann es auftritt.

Das Verhalten tritt mit und ohne aktivierten Debugausgaben auf.

Der gleiche Aufbau mit NodeMcu Firmware 3.0.0.0 und einem LUA Programm 
läuft über eine Stunde stabil.

Hat jemand einen Tipp für mich, wo ich schauen kann. bzw. was die 
Ursache sein könnte?

cu
Georg

: Bearbeitet durch User
von Ralf G. (ralg)


Lesenswert?

Habe gerade deinen etwas älteren Beitrag gelesen. Schon eine Lösung 
gefunden? Falls nicht: Ich habe festgestellt, dass mit 
'server.available()' zwar ein 'WiFiclient'-Objekt erzeugt wird, aber ein 
nachfolgendes 'client.available()' keine Daten 'meldet'. Ich warte 
einfach etwas auf die Daten:
1
#define BUFFER_SIZE 512
2
static char client_buffer[BUFFER_SIZE];
3
4
uint_fast8_t handle_client()
5
{
6
  memset( client_buffer, 0, BUFFER_SIZE );
7
  WiFiClient client = server.available();
8
  if ( !client )
9
    return 1;
10
  
11
  uint_fast16_t count = 0;
12
  for (uint_fast8_t i = 0; i < 20; i++)
13
  {
14
    count = client.available();
15
    if (count)
16
      break;
17
    delay(5);
18
  }
19
  if ( !count )
20
    return 2;
21
    
22
  for (uint_fast16_t i = 0; i < count; i++)
23
  {
24
    if ( client.connected() )
25
    { 
26
      client_buffer[i] = client.read(); 
27
    }
28
    else
29
    {
30
      client.stop();
31
      return 3;
32
    }
33
  }
34
35
// 
36
// weiter im Programm
37
//
38
39
  return 0;
40
}

von Georg W. (gewe)


Lesenswert?

Danke, für die Info.

Werde ich am Wochenende mal testen.

von Stefan F. (Gast)


Lesenswert?

Ralf G. schrieb:
> Ich habe festgestellt, dass mit
> 'server.available()' zwar ein 'WiFiclient'-Objekt erzeugt wird, aber ein
> nachfolgendes 'client.available()' keine Daten 'meldet'.

Das ist logisch.

Der server ist avalilable() sobald eine Verbindung aufgebaut wurde.
Der client ist available() sobald er Daten empfangen hat.

Bei UDP wäre das was anderes, denn da gibt es keinen Verbindungsaufbau.

Wenn du Zeichenketten mit variabler Länge empfangen willst, dann guck 
mal von diesem Beispiel ab: 
http://stefanfrings.de/esp8266/index.html#tcpsketch

Die Funktion append_until() wird hier wiederholt aufgerufen, um die 
empfangenen Zeichen einzusammeln bis ein bestimmtes Trennzeichen (z.B. 
Zeilenumbruch) empfangen wird. Danach wird die bis dahin empfangene 
Zeichenkette verarbeitet.

Ich bevorzuge in den meisten Anwendungen Zeichenketten gegenüber 
Rohdaten, weil man das leichter manuell simulieren kann. Den eventuell 
nötigen technischen Mehraufwand zum Parsen von Zahlen gönne ich mir. 
Soll der Computer doch für mich arbeiten, nicht umgekehrt.

Ich würde auch immer daran denken, was passiert (bzw. was passieren 
soll), wenn mehrere Verbindungen gleichzeitig bestehen. Sollen sie sich 
gegenseitig blockieren? Soll nur eine zugelassen werden und die anderen 
abgelehnt werden? Einfach nur eine Verbindung verarbeiten und die 
anderen ignorieren ist keine gute Idee, denn das steht einer sauberen 
Fehlerbehandlung im Weg. Dabei immer auch an das andere Ende der Leitung 
denken, wie soll das Fehler erkennen und reagieren?

TCP arbeitet einigermaßen Zuverlässig. Wenn du Daten empfängst, dann 
sind sie wahrscheinlich unverfälscht und in der richtigen Reihenfolge. 
Du musst aber jederzeit damit Rechnen, das eine Verbindung nicht 
aufgebaut werden kann, oder unerwartet abbricht, oder für bis zu einer 
Minute stockt, oder eine Bestätigung des Empfängers für erfolgreich 
übertragene Daten beim Sender nicht ankommt.

von Ralf G. (ralg)


Lesenswert?

Stefan ⛄ F. schrieb:
> Das ist logisch.

Und warum funktioniert's dann nicht? (Ist 'ne rhetorische Frage.) Der TO 
hat dein Beispiel in Verwendung.

von Georg W. (gewe)


Lesenswert?

Ralf G. schrieb:

> Und warum funktioniert's dann nicht? (Ist 'ne rhetorische Frage.) Der TO
> hat dein Beispiel in Verwendung.

Hallo Ralf,

ich denke ich kann die Frage jetzt mal vorübergehend beantworten.

Ich habe eine Nodemcu Applikation, die sauber funktioniert hat.

Diese habe ich zum erneuten Test auf ein ESP01-S Modul gespielt und ich 
bekam Verbindungsprobleme.

Die gleiche Applikation auf ein anderes ESP01-S Modul gespielt und es 
läuft wieder.

Danach habe ich das angepasste Beispiel von Stefan auf das 
"funktionsfähige" Modul gespielt und siehe da, es läuft vorläufig auch.

Die Module stammen aus zwei unterschiedlichen Bestellungen und so wie es 
aussieht, machen eventuell die Module aus einer Bestellung Probleme.

Ich werde mich nochmal melden, wenn ich mehr getestet habe.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.