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. Danke für die Hilfe
Da sind lauter Verbindungs Aufbau und -Abbau Sequenzen drin:
1 | 09:42:00.277870 IP 192.168.1.249.56971 > 192.168.1.246.8000: Flags [S], seq 894310395, win 29200, options [mss 1460,sackOK,TS val 24019376 ecr 0,nop,wscale 5], length 0 |
2 | 09:42:00.279457 IP 192.168.1.246.8000 > 192.168.1.249.56971: Flags [S.], seq 19588812, ack 894310396, win 1460, options [mss 730], length 0 |
3 | 09:42:00.279457 IP 192.168.1.249.56971 > 192.168.1.246.8000: Flags [R], seq 894310396, win 0, length 0 |
Man sieht auch dass der Client das Reset Paket zum Abbau der Verbindung sendet. Warum wissen wir nich, dafür bräuchte man den Source Code. Die vom Server zurück gesendete MSS ist mit 730 Bytes ziemlich klein - kann es sein dass der Client ein Paket mit mehr Bytes senden möchte?
Jim M. schrieb: > Man sieht auch dass der Client das Reset Paket zum Abbau der > Verbindung sendet. Warum wissen wir nich, dafür bräuchte man den Source > Code. > > Die vom Server zurück gesendete MSS ist mit 730 Bytes ziemlich klein - > kann es sein dass der Client ein Paket mit mehr Bytes senden möchte? Danke für deine Antwort! Wie sieht normalerweise ein Wiederaufbau einer unterbrochenen Verbindung aus? Ist ein Zeitlicher Ablauf wichtig oder reagiert sowas relativ schnell? Danke für die Hilfe
> 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).
:
Bearbeitet durch User
Foobar schrieb: > 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. Der conector gibt einen Padding Fehler zurück. Danke für die Hilfe
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.
Hmm Martin B. schrieb: > 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? Danke für die Hilfe
Mein_erstes_Mal schrieb: > 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. Was Lesestoff angeht, finde ich das für den Anfang nicht schlecht: https://www.avast.com/de-de/c-tcp-vs-udp-difference Und natürlich Wikipedia https://de.wikipedia.org/wiki/Transmission_Control_Protocol https://de.wikipedia.org/wiki/User_Datagram_Protocol
Hallo @Steve Steve van de Grens schrieb: > 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? Steve van de Grens schrieb: > 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? Steve van de Grens schrieb: > Wenn du die Fehlerbehandlung selbst implementieren willst, dann nimm > nicht TCP sondern UDP. Ich möchte nur das notwendigste selber machen. Habe hier von Codesys die TCP Lib und damit muss ich es zum laufen bringen. Danke für die Hilfe
Mein_erstes_Mal schrieb: > 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.
:
Bearbeitet durch User
Mein_erstes_Mal schrieb: > Also muss ich sehen das ich den TCP.Stream.State auswerte? Ich kenne die SPS nicht. Auf jeden Fall hat jeder TCP Socket einen Indikator, ob er open oder closed ist.
> 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. Wie geht man da vor? Danke für die Hilfe
Mein_erstes_Mal schrieb: > 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. Dazu gibt es die TCP Keepalive Option. Ich weiß aber nicht, ob deine SPS das können. Siehe https://de.wikipedia.org/wiki/Keepalive 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".
Foobar schrieb: > 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. Ja das stimmt so! Foobar schrieb: > 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. Foobar schrieb: > 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
Mein_erstes_Mal schrieb: > 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.
es ist leider noch etwas komplizierter oder auch merkwürdiger: Der Client, der die Verbindung aktiv aufbaut, setzt sie ja sofort wieder zurück. Und man schaue sich in debug.pcapng nicht nur die Verbindungen mit Port 8000 an, sondern auch noch die wenigen mit Port 8001.
Peter schrieb: > 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
Ist denn nun KEEPALIVE beidseitig aktiviert, oder nicht? LG, Sebastian
Sebastian W. schrieb: > Ist denn nun KEEPALIVE beidseitig aktiviert, oder nicht? > > LG, Sebastian Das weiß ich leider nicht. Finde keine Angabe in dr Lib.
Mein_erstes_Mal schrieb: > Finde keine Angabe in dr Lib. Du benutzt doch Codesys? Such mal im API nach KEEPALIVE. Das musst du schon selbst aktivieren, die Lib macht das ohne Aufforderung nicht ... LG, Sebastian
Sebastian W. schrieb: > Mein_erstes_Mal schrieb: >> Finde keine Angabe in dr Lib. > > Du benutzt doch Codesys? Such mal im API nach KEEPALIVE. Das musst du > schon selbst aktivieren, die Lib macht das ohne Aufforderung nicht ... > > LG, Sebastian Ja ich benutze Codesys. Finde zu Keepalive nichts.
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? Danke für die Hilfe
:
Bearbeitet durch User
> 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.
:
Bearbeitet durch User
> [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.
ok .... 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.
Martin B. schrieb: > versucht der Client im Abstand von etwa 20 ms neue Verbindungen aufzubauen Das ist viel zu schnell. Selbst im Bereich Leistungsstarker Cloud Server wiederholen wir frühestens nach 10 Sekunden.
> 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.
> Ein asynchroner connect, der sofort wieder geschlossen > wurde, sollte einen RST beim SYN/ACK erzeugen. Bestätigt: (non-blocking socket, connect, close) erzeugt: S -> S. -> R Und ich hatte schon gegrübelt, wie man sowas per socket-API hinbekommt ;-)
interessant. Was passiert denn, wenn kein SYN, ACK zurück kommt?
> 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.
Danke für die Info. Mit meinem alten Ubuntu 16 lief es noch etwas anders. Mit Ubuntu 23 jetzt so wie beschrieben. :-)
Guten Abend, habe eine Besserung im Verhalten. Dank Euch!! Schreibe sobald ich es verstehe genauer was ich verbrochen 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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.