Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!
folgendes Problem: Ein LV-Programm kommuniziert via TCP mit einem externen Geräte. Die Verbindung wird nur verwendet, um Befehle an das Gerät zu senden. Wird nun das Gerät, nachdem die Verbindung steht, ausgeschaltet, wird dies nicht von dem LV-Programm erkannt. Die Funktion TCP Schreiben wird fehlerfrei ausgeführt. Allerdings werden die Befehle nun nicht mehr mit einem TCP-ACK-Telegramm bestätigt. Läßt sich dies irgendwie erkennen?
Wird das Gerät nun wieder eingeschaltet und ein Befehl gesendet, tritt bei der Funktion TCP Schreiben der Fehler 66 (Der Übertragungspartner hat die Netzwerkverbindung beendet.) auf.
Gibt es eine Möglichkeit zu prüfen, ob eine aufgebaute TCP-Verbingung noch besteht?
Hmm... das Verhalten wundert mich einfach - hast du einen Timeout gesetzt? Eventuell wartet die Funktion auch nur darauf schreiben zu können und deswegen wird nicht sofort ein Fehler gebracht....
*kopfkratz* Würde mich aber eigentlich wundern, bei mir wurde TCP Verbindungsabbrüche bisher eig. immer richtig erkannt - allerdings resultierten die bei mir entweder aus Beenden der Gegenstelle (was ja doch noch deutlich geordneter ist als als einfach ausschalten) oder Abbruch WLAN Verbindung...
Zitat:Märchen und Geschichten werden erzählt am Lagerfeuer, technischen Fakten werden mitgeteilt (oder so). (Genauso wie Software nicht auf einem Server "herumliegt", die ist dort installiert.)
Timeout ist auf 500ms gesetzt. Das "TCP Schreiben" keinen Timeout meldet, liegt sicher daran, das die Daten ja erfolgreich gesendet werden. Das habe ich mit Wireshark überprüft. Das Ausbleiben des ACK der Gegenstelle führt dann zu weiteren Sendeversuchen.
Und die weiteren Sendeversuche werden dann beliebig oft wiederholt auch über den Timeout hinaus? Das finde ich extrem strange. Kann btw. auch bestätigen, dass die Verbindung bei Program mit dem Roten butten mittendrin unterbrechen richtig terminiert wird (mit Fehler an der Gegestelle das die Verbindung weg ist).
Ich persönlich würde denken, dass der Fehler irgendwo in der Kommunikation zwischen windows und Labview oder bei der Gegenstelle liegen muss. Ich meine, offensichtlich greift ja eben er Timeout gerade nicht richtig und ein wiederholtes mehrfaches Senden ohne Antwort sollte auch irgendwann dazu führen, dass windows merkt das die Verbindung weg ist. Und wenn das low level TCP IP ACK fehlt - dann SOLLTE Windows das merken.
Schließlich sollte dann in keinster weise ein erfolgreiches Senden registriert werden. Oder wird das von der Hardware der Gegenseite doch irgendwo erfolgreich empfangen und nur nicht mehr richtig verarbeitet weil das Gerät aus ist?...
Okay hab jetzt einfach mal bei mir getestet indem ich durch Kabelziehen nen Verbindungsfehler provoziert habe. Habs mir nicht im Detail angeschaut, aber tatsächlich scheint das erstmal mehr oder weniger normal weiterzulaufen bis irgendwo nen Überlauf zustandekommt (nehme mal an da ich regelmäßig werte per anfrage aktualisieren lasse, waren dem das irgendwann einfach zu viele Sachen die als zu senden noch im Puffer saßen ). Scheint also tatsächlich so zu sein, dass Labview damit zufrieden ist alles erfolgreich an Windows übergeben zu haben und bei Win der hauptmechanismus darin besteht das wenn windows merkt das eines der geräte die Verbindung aktiv terminiert, es dafür sorgt das es auch auf der Gegenstelle terminiert wird.
Komisch komisch....
Zwecks Workaround: Kriegst du denn vom Gerät antworten? Bzw. kannst du iwie antworten provozieren? Dann könntest du darüber "manuell" den "onlinestatus" abfragen...
Zitat:Märchen und Geschichten werden erzählt am Lagerfeuer, technischen Fakten werden mitgeteilt (oder so). (Genauso wie Software nicht auf einem Server "herumliegt", die ist dort installiert.)
(28.05.2014 11:51 )Kiesch schrieb: Und die weiteren Sendeversuche werden dann beliebig oft wiederholt auch über den Timeout hinaus?
Nein nicht beliebig oft. Max. 4 Wiederholungen habe ich gezählt, wobei die Zeit zwischen den Versuchen immer gößer wurde (z.B.: 0,5s; 1s; 2s; 4s).
Das Protokoll, welches verwendet wird, ist sehr "mistig". Es setzt vorraus, das jeder Befehl in einem separaten TCP-Frame gesendet wird. Dumm gelaufen, wenn man auf OSI Schicht 7 sitzt und keine Kontrolle über die Paketzusammensetzung hat. Deswegen wird der Nagle-Algorithmus abgeschaltet. Dies wird über die "wsock32.dll" realisiert.
Ich hatte gehofft, es gibt "Low Level" TCP-Funktionen, über die man einen Verbindungsabbruch erkennen kann.
01.06.2014, 12:59 (Dieser Beitrag wurde zuletzt bearbeitet: 01.06.2014 13:01 von rolfk.)
(28.05.2014 11:51 )Kiesch schrieb: Und die weiteren Sendeversuche werden dann beliebig oft wiederholt auch über den Timeout hinaus?
Nein nicht beliebig oft. Max. 4 Wiederholungen habe ich gezählt, wobei die Zeit zwischen den Versuchen immer gößer wurde (z.B.: 0,5s; 1s; 2s; 4s).
Das Protokoll, welches verwendet wird, ist sehr "mistig". Es setzt vorraus, das jeder Befehl in einem separaten TCP-Frame gesendet wird. Dumm gelaufen, wenn man auf OSI Schicht 7 sitzt und keine Kontrolle über die Paketzusammensetzung hat. Deswegen wird der Nagle-Algorithmus abgeschaltet. Dies wird über die "wsock32.dll" realisiert.
Ich hatte gehofft, es gibt "Low Level" TCP-Funktionen, über die man einen Verbindungsabbruch erkennen kann.
Die gibts eben nicht weil das TCP/IP Protokoll nicht so designt ist. Wenn eine Verbindung zustandekommt (Connection Request positiv befestigt) dann ist diese Verbindung erst mal einfach als gültig erkannt. Wenn eine Applikation an die Socketlibrary dann einen Buffer schickt um den zu versenden meldet diese Socketlibrary ganz einfach brav zurück dass das alles super erfolgreich war. Der Buffer wurde akzeptiert und die Verbindung wurde von der Gegenseite bis zu dem Zeitpunkt nicht terminiert also ist alles in Ordnung. Danach versucht die Socketlibrary um den Buffer zu verschicken, resp. sie tut es auch. Wenn sich in der Zwischenzeit die Gegenstation sang- und klanglos verabschiedet hat, ohne die Verbindung aktiv zu terminieren, läuft dieses Packet einfach ins Leere ohne dass die Socketlibrary das direkt sieht. Sie merkt es dann nach einiger Zeit weil das Packet nicht bestätigt wurde, aber das kann viele Gründe haben, also wird nicht gleich aufgegeben sondern mehrmals versucht das Packet nochmals zu verschicken. Das kann mit den Timeouts, die ja auch nicht zu kurz sein dürfen da eine Internetverbindung über einen Satallieten und/oder noch schlimmer eine 9600 Baud Modem Verbindung schon mal einige Sekunden Turnaroundtime haben kann, schnell mal mehr als eine Minute dauern. Erst dann beginnt die Socketlibrary anzunehmen dass die Gegenstelle vielleicht doch nicht mehr lebt und beginnt damit das Socket ihrerseits zu schliessen.
Die einzige Art um selber aktiv festzustellen dass die Gegenstelle wohl nicht mehr lebt ist um ein Kommando zu schicken und wenn die Antwort nicht innerhalb vernünftiger Zeit erfolgt (einige 100ms in einem lokalen Netzwerk aber mehrere Sekunden in Internetverbindungen) die Verbindung selber aktiv zu schliessen und wieder neu zu öffnen versuchen. Diese Art von Netzwerkkommunikation kann sehr zuverlässig sein, hat aber noch immer einige Sekunden Timeout bevor man das sang- und klanglose Verschwinden der Gegenstelle erkennen kann.
Wenn die Socketlibrary ein Telegramm verschickt und keine Antwort (trotz mehrmaliger Sendeversuche) erhält, wird dies doch sicher irgendwo vermerkt? Kann man so etwas nicht abfragen?
Gruß Micha
02.06.2014, 21:14 (Dieser Beitrag wurde zuletzt bearbeitet: 02.06.2014 21:32 von rolfk.)
(02.06.2014 10:42 )FEL schrieb: Danke Rolf für die Infos.
Wenn die Socketlibrary ein Telegramm verschickt und keine Antwort (trotz mehrmaliger Sendeversuche) erhält, wird dies doch sicher irgendwo vermerkt? Kann man so etwas nicht abfragen?
Gruß Micha
Nicht direkt. Der Socket liefert dann irgendwann einen Error zurück (vor allem bei einem TCP Read ein beliebiger anderer error dann Timeout) aber die Timeouts dafür in der Socketlibrary sind so lang, dass das im Normalfall fast nie sichtbar wird. Schliesslich soll die Socketlibrary eine TCP Schnittstelle die über ein 300 Baud Serialinterface geht nicht einfach killen, nur weil die Datenübertragung WAHNSINNIG langsam ist.
Also besser um das selber zu machen indem Du halt ein Kommando schickst von dem Du weisst dass da eine Antwort kommen sollte und dann mit kurzem Timeout widerholt versuchen die Antwort zu lesen. Wenn diese nicht innerhalb einer vernünftigen Anzahl Retries kommt, die Verbindung schliessen und wieder neu öffnen. Wenn das Öffnen dann einen Timeout gibt weisst Du endgültig dass dein liebes Device nicht mehr aktiv am Netzwerk ist.
Grundsätzlich gibt es die SO_KEEPALIVE option die man verwenden könnte um das Socket regelmässig ein leeres Keep Alive packet verschicken zu lassen wenn kein anderer Verkehr stattfindet. Die Default settings sind aber etwas lang um ein Verbindungsunterbruch feststellen zu können. Hier ist der MSDN Artikel und es wird auch erwähnt wie man mit WSAIoctl(.., SIO_KEEPALIVE, ...) auch diese Werte veränderen kann, aber das sinnvoll einzustellen ist nicht gerade trivial.
Selber würde ich normalerwise lieber mein eigenes KeepAlive machen mit einem bekannten Kommando/Response.