Guten Tag,
ich versuche gerade eine TCP Verbindung zwischen zwei SPSen zu programmieren.
Grundsätzlich funktioniert die Verbindung.
Wenn der Server nicht antwortet und der Client somit eine neue Verbindung aufbauen soll kommt es zu Fehlern und die Verbindung baut sich nicht auf.
Mit Wireshark habe ich da mal aufgezeichnet.
Ich erkenne aber nicht ganz das Problem.
Kann bitte jemand mal auf die Aufzeichnung gucken.
Wie sieht normalerweise ein Wiederaufbau einer unterbrochenen Verbindung
aus?
Da gibt es keinen Automatismus. Das muß die Anwendung selbst machen und auf TCP-Ebene besteht da kein Unterschied zu dem erstmaligen Aufbau.
Ist ein Zeitlicher Ablauf wichtig oder reagiert sowas relativ schnell?
Da gibt es keine Beschränkungen - kannst die Verbindung so schnell initiieren wie du willst.
Die Frage ist eher, warum sie unterbrochen wird - wenn das durch TCP selbst ausgelöst wird, ist das Timeout seeehr lang (je nach Auslöser Minuten bis Stunden, ohne TX unendlich).
Die Frage ist eher, warum sie unterbrochen wird - wenn das durch TCP
selbst ausgelöst wird, ist das Timeout seeehr lang (je nach Auslöser
Minuten bis Stunden, ohne TX unendlich).
Danke für die Hilfe.
Es ist so das es möglich ist das eine Sps mal wärmend dem Betrieb ausgeschaltet wird und die Ander weiter läuft.(im Moment zum testen stecke ich einfach das Kabel kurz aus)
Natürlich sollte sich in dem Fall nach dem Neustart die Verbindung erholen.
Ich erkenne durch einen Rx Timeout am client das die Verbindung nicht mehr läuft. Darauf möchte ich dann versuchen die Verbindung wieder auf zu bauen. dazu habe ich versucht ein Disponent und oder Reset des TCP conectors zu machen.
Jedoch schaffe ich es nicht mehr die Verbindung zu heilen.
Wenn Beide sauber neu starten geht es dann wieder.
Ein kurzes Ausstecken des Kabels ist übrigens etwas anderes als das Ausschalten eines der beteiligten Systeme. Beim Ausstecken des Kabels muss die TCP-Verbindung nicht abbrechen.
Natürlich gibt es einen RX Timeout, denn eine Antwort, die der Kommunikationspartner (möglicherweise) senden will, kann ja nicht ankommen. Wenn dann, nach dem Eintreten des Timeout, die Verbindung auf der einen Seite beendet wird, dann kann sie durchaus auf der anderen Seite noch bestehen bleiben. Mindestens bis alle vorgesehenen Wiederholungen abgelaufen sind und „unendlich lange“, wenn nichts gesendet wird.
Ein kurzes Ausstecken des Kabels ist übrigens etwas anderes als das
Ausschalten eines der beteiligten Systeme. Beim Ausstecken des Kabels
muss die TCP-Verbindung nicht abbrechen.
Heißt das ich den Test falsch mache?
Ist es besser die Versorgung der SPS auszuschalten?
Wo kann ich mich über so eine TCP Verbindung gut informieren? am Besten auf Deutsch?
Ich erkenne durch einen Rx Timeout am client das die Verbindung nicht
mehr läuft.
Bei einem TCP Socket kümmert sich das TCP Protokoll darum, dass alle gesendeten Daten ankommen und auch alle antworten. Die gesamte Fehlerbehandlung liegt im TCP Protokoll. Wenn sie versagt, wird die Verbindung getrennt. Das ist das einzige eindeutige Signal, auf das dein Anwendungsprogramm reagieren sollte.
Wenn du Verbindung trennst, während das Kabel nicht gesteckt ist, kommt dieses Trenn-Signal nicht an der anderen SPS an. Sie "denkt" du seist immer noch verbunden. Wenn sie nur eine Verbindung gleichzeitig kann, dann hängst du nun fest.
Wenn du die Fehlerbehandlung selbst implementieren willst, dann nimm nicht TCP sondern UDP.
Hallo @Steve
Steve van de Grens schrieb im Beitrag #7499366:
Bei einem TCP Socket kümmert sich das TCP Protokoll darum, dass alle
gesendeten Daten ankommen und auch alle antworten. Die gesamte
Fehlerbehandlung liegt im TCP Protokoll. Wenn sie versagt, wird die
Verbindung getrennt. Das ist das einzige eindeutige Signal, auf das dein
Anwendungsprogramm reagieren sollte.
Also muss ich sehen das ich den TCP.Stream.State auswerte?
Wenn du Verbindung trennst, während das Kabel nicht gesteckt ist, kommt
dieses Trenn-Signal nicht an der anderen SPS an. Sie "denkt" du seist
immer noch verbunden. Wenn sie nur eine Verbindung gleichzeitig kann,
dann hängst du nun fest.
Was meinst du mit nur einer Verbindung gleichzeitig?
Was meinst du mit nur einer Verbindung gleichzeitig?
Wenn der mindestens eine der beiden Seiten nur eine Verbindung zulässt, und die bei Abbruch der anderen Seite der Ansicht ist, die Verbindung liefe noch, ist erst einmal Sense, bis Timeout.
Beim Ausstecken des Kabels muss die TCP-Verbindung nicht abbrechen.
(Desktop-)Windows hat die Eigenheit, bei Carrier-loss (Stecker raus) alle TCP-Verbindungen des Interfaces zu schließen. Andere Systeme machen das nicht - wenn du das Kabel wieder reinsteckst geht's weiter ohne dass die Anwendung was merkt.
Wenn ich dich richtig verstehe, erzeugt der Client auf Anwenderebene ein RX-Timeout (getriggert durch Kabel rausziehen). Daraufhin soll der Client die Verbindung neu aufbauen - da mußt der schon eine Weile probieren, das Kabel ist ja draußen.
Das Log zeigt, dass der Client das auch probiert ([S]), der Server antwortet [S.], aber statt einem finalen ACK schickt der Client einen Reset zurück ([S] -> [S.] -> [R]). Das ist eher ungewöhnlich, dass ein Client ein Reset schickt. Irgend etwas passt ihm nicht.
Blöderweise ist in dem gesamten Log kein einziger erfolgreicher Verbindungsaufbau drin. Was auffällt ist, wie Jim schon erwähnte, die geringe mss, das heruntergesetzte win und das droppen der meisten Options (keine Timestamps etc) vom Server - irgendein minimal-TCP-Stack? Oder hängt da eine Firewall/VPN/NAT zwischen? Allerdings scheint es initial ja mal zu klappen - wäre halt interessant zu sehen, was da anders ist.
Also ich habe eben noch mal versucht zu debuggen.
Das Problem ist das der TCP Stream meldet das der Stream OPEN ist.
Aber keine Daten mehr an der Gegenstelle ankommen.
Was meinst du mit nur einer Verbindung gleichzeitig?
Ein normaler Webserver unterstützt hunderte Verbindungen gleichzeitig. Aber bei so kleinen Computern ist das nicht selbstverständlich. Wenn A eine Verbindung zu B aufgebaut hat, kann es gut sein, dass B keine weitere Verbindungsanfrage mehr annimmt (egal von wem). Deine Problembeschreibung scheint in diese Richtung zu gehen.
A baut Verbindung zu B auf
A und B sind verbunden
Kabel wird unterbrochen
A trennt die Verbindung, B bekommt das nicht mit (weil das Kabel unterbrochen ist)
A will eine neue Verbindung zu B aufbauen
B lehnt das ab, weil B "denkt" es sei bereits Verbunden und auch nur eine gleichzeitige Verbindung erlaubt.
Am Besten sorgst du dafür, dass beide SPS alle paar Sekunde irgend etwas senden. Denn nur beim Senden erkennt das TCP Protokoll, ob die Verbindung noch funktioniert. Jedes gesendete Paket (oder eine Serie von Paketen) wird vom Empfänger bestätigt. Bleibt diese Bestätigung aus, wiederholt der Sender. Klappt es trotz mehrfacher Wiederholung nicht, wird die Verbindung geschlossen. So sorgst du dafür, dass beide Geräte die unterbrochene Leitung nach einer Weile erkennen, die Verbindung schließen und für eine neue Verbindung bereit werden.
Aber habe Geduld, das dauert typischerweise 1-2 Minuten.
Ohne Keepalive Option muss man das halt im Anwendungsprogramm implementieren. Es geht darum, dass beide Seiten sich regelmäßig irgend etwas senden, um zu sagen "hallo, ich bin noch da" -> "ja, habe ich sehe dich".
Wenn ich dich richtig verstehe, erzeugt der Client auf Anwenderebene ein
RX-Timeout (getriggert durch Kabel rausziehen). Daraufhin soll der
Client die Verbindung neu aufbauen - da mußt der schon eine Weile
probieren, das Kabel ist ja draußen.
Das Log zeigt, dass der Client das auch probiert ([S]), der Server
antwortet [S.], aber statt einem finalen ACK schickt der Client einen
Reset zurück ([S] -> [S.] -> [R]). Das ist eher ungewöhnlich, dass ein
Client ein Reset schickt. Irgend etwas passt ihm nicht.
Kannst du mir bitte erklären wie ich das Log richtig lesen Kann? wo finde ich ([S]) usw?
Den Reset habe ich eingebaut da ich dachte das dies vor dem neu verbinden Sinnvoll wäre.
Blöderweise ist in dem gesamten Log kein einziger erfolgreicher
Verbindungsaufbau drin. Was auffällt ist, wie Jim schon erwähnte, die
geringe mss, das heruntergesetzte win und das droppen der meisten
Options (keine Timestamps etc) vom Server - irgendein minimal-TCP-Stack?
Oder hängt da eine Firewall/VPN/NAT zwischen? Allerdings scheint es
initial ja mal zu klappen - wäre halt interessant zu sehen, was da
anders ist.
Reiche morgen ein Log nach das den Funktionierenden Teil auch zeigt.
Danke und schönen Abend
Den Reset habe ich eingebaut da ich dachte das dies vor dem neu
verbinden Sinnvoll wäre.
Das ist ja auch OK so. Nur ist die andere SPS nicht bereit, eine zweite Verbindung anzunehmen. Sie denkt, dass die erste Verbindung noch besteht. Denn deren Ende hat sie (dank des unterbrochenen Kabels) verpasst.
Kannst du mir bitte erklären wie ich das Log richtig lesen Kann? wo
finde ich ([S]) usw?
Hinter Flags (siehe 2. Posting im Thread)
Den Reset habe ich eingebaut da ich dachte das dies vor dem neu
verbinden Sinnvoll wäre.
Ein Reset auf der alten Verbindung wäre OK, er wird aber auf die neue Verbindung geschickt.
roehrmond schrieb:
Nur ist die andere SPS nicht bereit, eine zweite Verbindung anzunehmen.
Es kommt ja ein SYN-ACK. Der Server ist bereit, eine neue Verbindung aufzubauen, der Client hat seine Meinung geändert und will nicht mehr - schickt einen Reset von dem Port, auf dem er gerade eine neue Verbindung angefragt hat.
Guten tag,
sorry das ich erst jetzt schreibe.
Waren aber wichtigere Dinge auf dem Programm.
Ich habe eine Aufzeichnung gemacht wo die Kommunikation zwischen client und server auf Port8001 funktioniert.
Die Verbindung zwischen Client und server auf Port 8000 ist hier unterbrochen.
Danke für die Hilfe
Habe jetzt zum besseren Verständnis auf einer SPS Client und auf der anderen SPS Server laufen.
Vorher hatte ich Client und Server auf beiden SPSen.
Ich kommuniziere nun auf Port8000.
Die Aufzeichnung von Wiresharke beinhaltet zu erst die reguläre Kommunikation.
Dann stecke ich die Stromversorgung des Servers aus und wieder ein.
Die Kommunikation erholt sich nicht.
Der Client meldet PENDING.
Was bedeutet das?
Wie kommt man in der Theorie aus diesem Zustand raus?
Ich habe eine Aufzeichnung gemacht wo die Kommunikation zwischen client
und server auf Port8001 funktioniert. [debug2.pcapng]
Ja, aber der Verbindungsaufbau ist nicht drin. Was man aber sieht, ist, dass die Pakte anscheinend eine konstante Größe von 611 Bytes haben, passen also ohne Fragmentierung in die kleine mss vom Server.
Die Verbindung zwischen Client und server auf Port 8000 ist hier
unterbrochen.
Nicht wirklich - client und server unterhalten sich wie gestern auch, der client kneift aber immer wieder den Schwanz ein.
Schmeiß halt mal das Reset-senden aus deinem Programm raus und probier's dann. Der Reset kommt eh, wenn der Server was sendet und der Client die Verbindung nicht mehr kennt.
Das mit dem keep-alive kannst du vergessen - keep alive timeout ist normalerweise 2 Stunden - in der Praxis eher uninteressant.
[debug3.pcapng]
Ich kommuniziere nun auf Port8000.
Die Aufzeichnung von Wiresharke beinhaltet zu erst die reguläre
Kommunikation.
Sieht ok aus.
Dann stecke ich die Stromversorgung des Servers aus und wieder ein.
Bei ca. 17:47:11.447638. Der Client will noch 4 Pakete rausschicken, bekommt aber keine Antwort. Daraufhin reagiert er panisch mit einenem Sturm von Verbindungsanfragen [S] - das solltest du limitieren (z.B. <10 pro Sekunde). Ab 17:47:15.372691 meldet sich der Server wieder, meldet aber erstmal ein "Connection refused" auf die Anfragen (der Dienst läuft wohl noch nicht). Ab 17:47:15.549115 ist er wieder bereit und akzeptiert die Verbindungsanfragen ([S.]) aber der Client kneift wieder den Schwanz ein (aka schickt einen Reset statt ein ACK).
Die Kommunikation erholt sich nicht.
Der Client meldet PENDING.
Wie auch - er (der Client) verweigert den Verbindungsaufbau. Wie gesagt, schmeiß mal das Reset-senden aus deinem Code raus.
Bis Paket 614 kommunizieren beide miteinander. 615 ist eine Quittung vom Client und das nächste Paket vom Client, Paket 632 wird nicht mehr quittiert.
Nach fast einer Sekunde (ist das der Timeout-Wert?) versucht der Client im Abstand von etwa 20 ms neue Verbindungen aufzubauen. Die „alte“ Verbindung besteht auf dem Client noch. Sie wird 6,5 s später nach 5 Paketwiederholungen abgebrochen und zwar durch einen RESET des Servers. Das ist zu erwarten, denn auf dem Server existiert die Verbindung nicht mehr und nachdem er wieder läuft, schickt er nach Empfang eines TCP-Pakets für eine nicht existierende Verbindung ein RESET (Paket 1898).
Ab Paket 1111 läuft der Server wieder. Aber der Port 8000 ist zunächst nicht aktiv. Das sieht man daran, dass jedes Paket mit SYN mit einem RESET beantwortet wird. Das dauert aber nur ungefähr 170 ms und dann antwortet der Server mit SYN, ACK, was dann zu den RESET vom Client führt.
Auch nachdem der Server mit Paket 1898 die „alte“ Verbindung auf dem Client beendet, ändert sich nichts. Es kommen weiterhin die RESET vom Client.
Das zum Ablauf.
Das „pending“ würde ich so verstehen wollen, dass die noch bestehende Verbindung stört. Aber das würde ich dann trotzdem noch in der Doku nachlesen. :-)
Das Problem ist also womöglich, dass eine neue Kommunikation versucht wird, obwohl die vorherige auf dem Client noch nicht beendet ist. Das Beenden der alten Verbindung nach dem Read-Timeout funktioniert definitiv nicht. Das würde ich als erstes korrigieren.
versucht der Client im Abstand von etwa 20 ms neue Verbindungen aufzubauen
Er muss da eh was Wildes machen - ist ja nicht so, dass er wiederholt versucht EINE neue Verbindung aufzubauen, sondern das sind alles parallele Verbindungsanfragen! Rein theoretisch könnten die alle noch bestätigt werden. Da allerdings keinerlei SYN-Retries zu sehen sind, hat der Client anscheinend die Verbindung nach einem non-blocking-connect direkt wieder geschlossen. Das würde auch das Verhalten erklären, dass man sieht, wenn der Server endlich mal antwortet. Ein asynchroner connect, der sofort wieder geschlossen wurde, sollte einen RST beim SYN/ACK erzeugen.
Was passiert denn, wenn kein SYN, ACK zurück kommt?
Nichts, nur das rausgehende SYN, sonst nichts. Wenn ich das ganze in eine Schleife packe, kommt genau der Trace von Peter raus - lauter SYNs mit hochlaufenden Portnummern und später dann lauter SYN->SYNACK->RST.