Hallo,
ich betreibe zwei ESP8266 als WiFiServer und WiFiClient. Normalerweise
funktioniert alles wie es soll.
Es taucht allerdings ein Problem auf, wenn der Client sich nicht
"normal" abmeldet, sondern z.B. einfach die Stromversorgung
abgeschaltet wird und er so auf dem Netzwerk fällt. In diesem
Fall erkennt der Server nicht, dass die Verbindung nicht mehr zum
Client besteht. Er bleibt deswegen für einen neuen Clients gesperrt
bis nach ca. 15 bis 20 Minuten wohl eine anderer Mechanismus
die Verbindung beendet.
Meine Anwendung benötigt, dass der Client sich normalerweise nicht disconnected , sondern solange mit dem Server verbunden bleibt und
von diesem mit Daten versorgt wird bis der Client sich "normal"
abmeldet.
Ich benutze client.flush und client.disconnected() beim Server,
das scheint aber für diesen Fall nicht auszureichen. Meine
umfangreichen Recherchen im WEB habe eigentlich keine Lösung des
Problems gefunden.
Üblicherweise kann man einstellen, wie lange ein Server eine Client-Verbindung aufrechterhält auch ohne dass dieser etwas schickt (timeout) - den kürzer setzen und dann ggfs keepalive einbauen.
Üblicherweise kann man einstellen, wie lange ein Server eine
Client-Verbindung aufrechterhält auch ohne dass dieser etwas schickt
(timeout) - den kürzer setzen und dann ggfs keepalive einbauen.
Ich kenne die Server-Seite von ESP8266 APIs nicht. Nebenbei, du verrätst uns nicht mal welche Umgebung (API, Sprache, Toolkits, ...) geschweige denn welche Protokolle oberhalb Layer 2 du verwendest. Aus "WiFi" kann man erraten was L1 (Phys) und L2 (MAC) sind, aber der Rest fehlt.
Daher nur ein paar generelle Hinweise.
Normalerweise baut man einen Server "concurrent" auf. D.h. der Server kann mehrere Verbindungen zu Clients gleichzeitig abhandeln. Dabei fällt ein hängender Client nicht so ins Gewicht und kann irgendwann von irgend einem Timeout abgeräumt werden. Nur bei ganz einfachen Diensten und wenn es eben nicht auf allzeitige Verfügbarkeit des Servers ankommt baut man einen iterativen Server. Aber genau das scheinst du gemacht zu haben.
D.h. an dem Punkt würde ich mal die gesamte Architektur überdenken und tief in das verwendete API und die angebotenen Mechanismen des Systems schauen um einen concurrent Server zu bauen.
Die bereits erwähnten Timeouts musst du sowieso haben, egal ob iterativ oder concurrent. Bei concurrent hast du nur mehr Luft und kannst dem Client mehr Zeit für z.B. Wiederholungen geben wenn die Verbindung gestört ist.
Aus "WiFi" kann
man erraten was L1 (Phys) und L2 (MAC) sind, aber der Rest fehlt.
Ich habe kein Problem damit zuzugeben, dass ich speziell davon
keine Ahnung habe. Ich verwende die landläufigen Libraries in diesem
Fall für den ESP8266 in C und benutze Platformio. Ich bitte also um
Nachsicht bei meiner Frage.
Die Librarybeschreibungen die ich dazu gefunden haben sagen für mich
nichts darüber aus, was hinter den Funktionen im Detail steckt und wie
man eventuelle Probleme der beschriebenen Art verhindert oder umgeht.
Oder wie und wo man Timeouts anwendet oder benutzt.
Meine Anwendung basiert auf allseits verfügbare WiFi Server/Client
Examples aus dem WEB.
Die Librarybeschreibungen die ich dazu gefunden haben sagen für mich
nichts darüber aus, was hinter den Funktionen im Detail steckt und wie
man eventuelle Probleme der beschriebenen Art verhindert oder umgeht.
Oder wie und wo man Timeouts anwendet oder benutzt.
Meine Anwendung basiert auf allseits verfügbare WiFi Server/Client
Examples aus dem WEB.
Wenn man wüsste, welche Library du verwendest (Link?!), gäbe es vielcht jemand, der die kennt oder sachkundiger als du bist.
Die Doku von Arduino.cc kannst du schon mal knicken, weil Arduino nichts mit dem ESP8266 am Hut hat.
Der Arduino Core für den ESP8266 basiert auf auf den NONOS SDK von Espressif und stammt weder von Espressif noch von Arduino. Die Autoren haben sich bemüht, das Verhalten der originalen Arduino Variante so weit es geht nachzuahmen. Das SDK von Espressif verwendet wiederum lwIP.
Sende periodisch (z.B. alle 15s) Pakete, und wenn Du auf drei oder 4
keine Antwort bekommen hast, dann ist die Gegenstelle weg.
So würde ich es auch empfehlen. Da die Gegenseite ihr Verschwinden nicht signalisiert, bleibt die Verbindung für immer bestehen. Es sei denn, deine Software auf dem ESP8266 trennt sie aktiv.
Vielen Dank für die Klarstellung. Wusste ich nicht, habe einfach ein
Beispiel übernommen und mir weiter keine Gedanken gemacht, nachdem
eigentlich alles soweit gut gelaufen ist.
Der Lösungsansatz von Frank K. hat bei mir nicht geklappt, da der Server
unentwegt sendet auch ohne Client.
Habe jetzt noch einen weiteren Ansatz mit Ping gefunden. Werde das
mal versuchen.
Der Lösungsansatz von Frank K. hat bei mir nicht geklappt, da der Server
unentwegt sendet auch ohne Client.
Dann hast Du das Konzept nicht verstanden.
Client UND Server müssen regelmässig Daten senden. Wenn eine Seite nach x Sekunden immer noch nichts zu erzählen hat, wird ein Keepalive-Paket geschickt, das nur bescheid sagt, dass der Absender noch da ist.
Wenn x Sekunden lang nichts von der Gegenstelle kam, wird im Fall des Servers der Client abgeworfen, im Fall des Clients wird die Verbindung zum Server getrennt und neu aufgebaut.
Habe jetzt noch einen weiteren Ansatz mit Ping gefunden.
Solange Du Einfluss auf das Protokoll hast, ist sowas Murks. Dass ICMP durchgeht, heisst noch lange nicht, dass TCP auch durchgeht und die Verbindung noch lebt.
Client UND Server müssen regelmässig Daten senden. Wenn eine Seite nach
x Sekunden immer noch nichts zu erzählen hat, wird ein Keepalive-Paket
geschickt, das nur bescheid sagt, dass der Absender noch da ist.
Ich bin lernwillig!
Weitere dumme Frage: Auf welcher Ebene muss denn das passieren? Macht
das das Protokoll selber oder muss ich das auf meiner Datenebene machen?
Meine Erfahrung ist, dass die TCPServer TCPClient Verbindung grundsätzlich
solange hält bis der Client sich ordentlich abmeldet oder (aus
irgend einem Grunde bei mir nach ca. 15 bis 20 Minuten) der Server die
Verbindung abbricht wenn der Client nicht mehr im Netzwerk ist.
Wenn ich eine TCP Verbindung als TCP-Client mit einem PC Tool (z.B
Hercules_3_2-8) zu einem TCP Server aufbaue, sehe ich keine Möglichkeit
wie ich das oben bewerkstelligen soll. Die Verbindung bleibt aber dennoch
beliebig lange erhalten bis ich selber die Verbindung schließe.Das
Tool merkt auch nicht (jedenfalls nicht gleich) wenn der Client weg ist.
Wenn ich eine TCP Verbindung als TCP-Client mit einem PC Tool (z.B
Hercules_3_2-8) zu einem TCP Server aufbaue, sehe ich keine Möglichkeit
wie ich das oben bewerkstelligen soll.
Vielleicht solltest Du erstmal beschreiben, was Du da genau tust. Bisher war von "Deiner Anwendung" die Rede, da gehe ich davon aus, dass Du die volle Kontrolle über das Protokoll und den Code auf beiden Seiten hast.
Vielleicht solltest Du erstmal beschreiben, was Du da genau tust. Bisher
war von "Deiner Anwendung" die Rede, da gehe ich davon aus, dass Du die
volle Kontrolle über das Protokoll und den Code auf beiden Seiten hast.
Habe die volle Kontrolle nur über den Server , aber nicht über
alle Clients!
Im Prinzip habe ich eine Server (ESP8266)der Daten von Sensoren
sammelt und diese an einen Client weitergeben kann wenn einer
verbunden ist.
Ein Client kann z.B. ein PC Tool sein, das die Daten visualisiert,
oder nur auflistet. Es kann aber auch eine andere HW (ESP8266)
sein die nur bestimmte Daten aus dem Datenstrom herausnimmt und
darstellt bzw. anzeigt.
Dann ist Dein Stichwort TCP-Keepalives, dann kümmert sich der
TCP/IP-Stack darum.
Das scheint er eben nicht zu machen, jedenfalls sieht es für mich so
aus. Ich würde gerne nach maximal einer Minute wissen ob die
Verbindung vom Server zum Client noch da ist oder nicht.
Der Server schickt ein ICMP Packet Typ 8 (Echo Request). Der Client antwortet dann mit einem ICMP Packet Typ 0 (Echo Reply).
Ist der Client Offline, dann wird die Anfrage natürlich nicht beantwortet.
Das Ganze kann parallel zu anderer IP Communication laufen, stört also i.A. nicht.
Denn ohne ICMP würde IP ja nicht wirklich funktionieren, oder?
Jein. ICMP Echo ("Ping") ist tatsächlich verzichtbar. Wenn man ICMP Destination unreachable filtert, kann insbesondere UDP zum Ärgernis werden, ausserdem macht man damit die Path MTU Discovery kaputt. ICMP Time exceeded ist auch nützlich, ohne funktioniert Traceroute nicht.
Auf der Verbindung, die du aufrecht erhalten willst.
Meine Erfahrung ist, dass die TCPServer TCPClient Verbindung
grundsätzlich solange hält bis der Client sich ordentlich abmeldet
Irgendwann wirst du vielleicht die Erfahrung machen, dass Firewalls und andere Netzwerk-Komponenten die Eigenschaft haben, "eingeschlafene" Verbindungen zu trennen. Schlimmer noch: Manche trennen sogar aktiv genutzte Verbindungen, wenn sie ein gewisses Alter überschreiten.
Generell sollten Netzwerk-Programme stets sauber mit unerwarteten Verbindungsabbrüchen sowie Timeouts (keine Antwort) umgehen können. Denn dass eine Verbindung immer stabil bleibt, ist ungewiss. TCP sorgt dafür, dass die Daten in der richtigen Reihenfolge und niemals doppelt beim Empfangenden Programm ankommen. Sollte das aus irgend einem Grund nicht klappen, trennt der IP-Stack üblicherweise die Verbindung.
CMP Echo ("Ping") ist tatsächlich verzichtbar. Wenn man ICMP
Destination unreachable filtert, kann insbesondere UDP zum Ärgernis
werden, ausserdem macht man damit die Path MTU Discovery kaputt.
Das war genau das was ich meinte. "Ping" besteht ja letztendlich nur aus zwei ICMP Packeten mit unterschiedlichen Typen (8 & 0).
Der Gesamtmechanismus, also ICMP insgesamt, ist schon wichtig.