100%ig Zuverlässige TCP/IP Kommunikation...



  • pale dog schrieb:

    hustbaer schrieb:

    Und eben den Punkt dass der Umstand dass man etwas senden konnte nicht bedeutet dass es auch empfangen werden konnte.

    doch, schon, daten werden vom empfänger bestätigt. kommte keine bestätigung, versucht's der sender nochmal. ist im TCP alles schon eingebaut. wenn die verbindung fehlerfrei geschlossen wird, haben beide teilnehmer alles bekommen, was der andere gesendet hat.

    Nein eben nicht! Du redest hier nur von Ebene 3 und da stimmt das alles auch... meine Anwendung läuft aber auch Ebene 8!
    Und da kann ich z.B. genau in dem Zeitpunkt in einen Timeout laufen, während das Paket gerade auf Ebene 3 als angekommen bestätigt wurde...

    Das Warten geschieht übrigens mittels "WSAWaitForMultipleEvents", wobei man ja den Timeout angeben kann. Und vorbereitet wird der Socket mittels "WSAAsyncSelect und FD_READ|FD_CLOSE".



  • Jochen Kalmbach schrieb:

    Nein eben nicht! Du redest hier nur von Ebene 3 und da stimmt das alles auch... meine Anwendung läuft aber auch Ebene 8!
    Und da kann ich z.B. genau in dem Zeitpunkt in einen Timeout laufen, während das Paket gerade auf Ebene 3 als angekommen bestätigt wurde...

    ja, das kann passieren, aber wenn du beim timeout z.b. den socket killst, kriegt die gegenstelle das mit und weiss, dass obwohl sie alles senden konnte, du die kommunikation abgebrochen hast. selbst wenn die gegenstelle schon die close-sequenz gestartet hat, bemerkt sie ein killen der verbindung deinerseits.
    ist das netz down o.ä. und die gegenstelle bekommt deinen erzwungenen verbindungsabbruch nicht mit, dann misslingt auch das von ihr initiierte schliessen der verbindung. in allen fällen klappt die erkennung, erfolg oder misserfolg, sehr zuverlässig. wenn's nicht so wäre, würde das ganze internet verdammt schlecht funktionieren 😉

    Jochen Kalmbach schrieb:

    Das Warten geschieht übrigens mittels "WSAWaitForMultipleEvents", wobei man ja den Timeout angeben kann. Und vorbereitet wird der Socket mittels "WSAAsyncSelect und FD_READ|FD_CLOSE".

    beim FD_CLOSE kannste ja mit dem 'lparam' o.ä. herausfinden, ob irgendwas schief ging. alle wichtigen events sollten eigentlich bis zum layer 8 irgendwie durchgereicht werden...



  • pale dog schrieb:

    hustbaer schrieb:

    Und eben den Punkt dass der Umstand dass man etwas senden konnte nicht bedeutet dass es auch empfangen werden konnte.

    doch, schon, daten werden vom empfänger bestätigt. kommte keine bestätigung, versucht's der sender nochmal. ist im TCP alles schon eingebaut. wenn die verbindung fehlerfrei geschlossen wird, haben beide teilnehmer alles bekommen, was der andere gesendet hat.

    Äh. Das ist mir schon klar dass das gilt wenn die Verbindung "gracefully closed" wurde.
    Bloss was ist wenn sie abreisst?
    Was bringt mir ein Protokoll welches nur dann "korrekt" funktioniert wenn die Verbindung nie abreisst?
    Verstehe das nicht so ganz... *wunder*



  • hustbaer schrieb:

    Bloss was ist wenn sie abreisst?

    wenn die verbindung abreisst dann muss die ganze sendung irgendwann wiederholt werden (unter der voraussetzung, dass beide 100%ige gewissheit brauchen).

    hustbaer schrieb:

    Was bringt mir ein Protokoll welches nur dann "korrekt" funktioniert wenn die Verbindung nie abreisst?

    kein verbindungsorientiertes protokoll funktioniert richtig, wenn die verbindung abreisst 😉

    btw: ich weiss, dass manche lieber ihre eigenen protokolle mit irgendwelchen packet-ID's und acknowledgements auf TCP aufsetzen, anstatt einer seit jahrzehnten bewährten technik zu vertrauen, aber dann kann man besser gleich UDP nehmen.
    das geht dann meistens sogar schneller 🙂



  • pale dog schrieb:

    hustbaer schrieb:

    Bloss was ist wenn sie abreisst?

    wenn die verbindung abreisst dann muss die ganze sendung irgendwann wiederholt werden (unter der voraussetzung, dass beide 100%ige gewissheit brauchen).

    hustbaer schrieb:

    Was bringt mir ein Protokoll welches nur dann "korrekt" funktioniert wenn die Verbindung nie abreisst?

    kein verbindungsorientiertes protokoll funktioniert richtig, wenn die verbindung abreisst 😉

    btw: ich weiss, dass manche lieber ihre eigenen protokolle mit irgendwelchen packet-ID's und acknowledgements auf TCP aufsetzen, anstatt einer seit jahrzehnten bewährten technik zu vertrauen, aber dann kann man besser gleich UDP nehmen.
    das geht dann meistens sogar schneller 🙂

    Ich meinte mit "Protokoll" nicht TCP/IP sondern ein "Anwendungsprotokoll" welches auf TCP/IP (oder sonstwas) aufsetzt. Eben etwas mit dem ich verteilte Transaktionen machen kann, oder eben so eine "100%ige Sicherheit" bekommen kann.

    Vielleicht habe ich Jochen doch nicht richtig verstanden, aber ich habe den Eindruck dass es darum geht einen Fall wo die Verbindung abgerissen ist richtig zu handhaben. Und wenn die Verbindung abgerissen ist können eben die netten Garantien von TCP/IP die nur für den Fall gelten wo die Verbindung nicht abgerissen ist auch logischerweise nicht helfen. Klar jetzt was ich meine?



  • hustbaer schrieb:

    Vielleicht habe ich Jochen doch nicht richtig verstanden, aber ich habe den Eindruck dass es darum geht einen Fall wo die Verbindung abgerissen ist richtig zu handhaben.

    das hab' ich auch so verstanden.

    hustbaer schrieb:

    Und wenn die Verbindung abgerissen ist können eben die netten Garantien von TCP/IP die nur für den Fall gelten wo die Verbindung nicht abgerissen ist auch logischerweise nicht helfen. Klar jetzt was ich meine?

    klar, aber wenn die verbindung abgerissen ist, kann gar nichts mehr helfen, ausser vielleicht irgendwelche alternativen kommunikationswege. das wichtigste aber ist doch, dass beide kommunikationspartner feststellen können, das irgendwas schief gegangen ist und das bringt TCP schon mit.
    es gibt keine absolute sicherheit, dass die übertragung immer klappt.
    denn wenn das netz tot ist, helfen auch keine auf TCP aufgesetzten protokolle mehr.
    🙂



  • Selbst wenn die Verbindung abreißt. Den Timeout verursacht doch nicht Ebene 8 oder ire ich mich da. Man teil der API doch mit wann der Timeout kommen soll. Wenn ein Timeout dann auf TCP-Ebene da ist dann sendet der Empfänger auch kein OK mehr an den Server und teil dem Programm mit das ein Timeout da ist.
    Habe Jochen vielleicht auch falsch verstanden.
    Ich verstehe aber nicht was Schicht 3 ist den TCP im OSI-Model läuft in Schicht 4 und das Programm selbst in Schicht 7. Schicht 3 ist das Netzwerk selbst.
    Schicht 4 ist das Protokoll. Schicht 7 macht nur das was im die Darunterliegenden Mitteilen.



  • Unix-Tom schrieb:

    Selbst wenn die Verbindung abreißt. Den Timeout verursacht doch nicht Ebene 8 oder ire ich mich da.

    das core TCP protocol kennt keine time-outs während eine verbindung steht, aber der socket-layer bietet eine keepalive-option an, um die verbindung zu checken. dabei werden, falls lange nichts los war, pakete ohne inhalt (also nur die header) verschickt, die der andere beantworten muss. 🙂



  • TCP ist immernoch ein 4-Schichtenmodell bevor es ISO-8-Schichtenmodelle gabs 😛



  • Dann sagen wir Schicht 4 (TCP) und 7 (Application-Layer)... sorry... jeweils um eins verrutscht... aber um das geht es mir ja gar nicht 😉
    http://de.wikipedia.org/wiki/OSI-Modell

    Ich wiess nicht wie Windows das abhandelt, aber aus der Erfahrung raus wird der Timeout nicht in Ebene 4 gemacht sondern weiter oben... denn sonst hätte ich das Problem ja nicht 😉



  • Wenn du einen Timeout bekommst dann hast du aber noch immer Daten im Buffer (wurden ja auch in Schicht 3 bereits an den Sender mit OK bestätigt) die du dann trotzdem noch holen kannst oder hast du nach Timeout keine Zugriff mehr auf den Socket um ein Read auszuführen.



  • Das hilft mir aber vermutlich auch nicht, da es dann wieder eine andere Race-Condition gibt, zwischen dem "timeout", "lesen" und "zurücksetzen" des Sockets...
    Ich werd wohl nicht über eine eindeutige ID drum rum kommen...

    Danke für die vielen Beiträge!



  • pale dog schrieb:

    hustbaer schrieb:

    Vielleicht habe ich Jochen doch nicht richtig verstanden, aber ich habe den Eindruck dass es darum geht einen Fall wo die Verbindung abgerissen ist richtig zu handhaben.

    das hab' ich auch so verstanden.

    hustbaer schrieb:

    Und wenn die Verbindung abgerissen ist können eben die netten Garantien von TCP/IP die nur für den Fall gelten wo die Verbindung nicht abgerissen ist auch logischerweise nicht helfen. Klar jetzt was ich meine?

    klar, aber wenn die verbindung abgerissen ist, kann gar nichts mehr helfen, ausser vielleicht irgendwelche alternativen kommunikationswege. das wichtigste aber ist doch, dass beide kommunikationspartner feststellen können, das irgendwas schief gegangen ist und das bringt TCP schon mit.

    Richtig. Bloss kann z.B. der Kommunikationspartner der zuletzt noch gesendet hat nicht wissen wieviel schon beim anderen angekommen ist.

    es gibt keine absolute sicherheit, dass die übertragung immer klappt.
    denn wenn das netz tot ist, helfen auch keine auf TCP aufgesetzten protokolle mehr.
    🙂

    Wenn das Netzt tot ist kann man solange nixmehr machen bis man wieder ein Netz hat. Dann kann man nen neue Verbindung aufbauen und von vorne anfangen. Um aber von vorne anfangen zu können und dabei nicht Gefahr zu laufen Daten doppelt abzuspeicher/Dinge doppelt zu machen muss man selbst irgendwie dafür sorgen dass beim "Wiederaufnehmen" eines Vorganges ermittelt werden kann auf welcher Seite welcher Teil bereits ausgeführt wurde.

    @Jochen Kalmbach: vergiss die Schichten, darum gehts nicht 😉
    Wenn du irgendwo einen Fehler feststellst mach den Socket zu und ignorier einfach alles was du noch nicht gelesen hast. Dein (Applikations-)Protokoll muss sowieso damit klarkommen dass jederzeit die Verbindung getrennt werden kann. Wenn es passiert, und du noch ein paar Pakete von der Gegenstelle im Empfangspuffer stehen hast die du dann nichtmehr auswertest - egal, der Abbruch hätte genausogut vor dem Empfangen dieser Pakete stattfinden können.



  • Jochen Kalmbach schrieb:

    Das hilft mir aber vermutlich auch nicht, da es dann wieder eine andere Race-Condition gibt, zwischen dem "timeout", "lesen" und "zurücksetzen" des Sockets...
    Ich werd wohl nicht über eine eindeutige ID drum rum kommen...

    Danke für die vielen Beiträge!

    Es ist natürlich nur eine Vermutung, da ich den Code nicht kenne, aber ich werde das Gefühl nicht los das Du einen grundsätzlichen Designfehler vorliegen hast. In Schicht 7 (um mal beim OSI model zu bleiben) solltest Du gar nichts mehr mit timeouts, protokollen usw zu tuen haben, weil dies in den unteren Schichten komplett erledigt wird. Genaugenommen muss es vollkommen egal sein welches technische Protokoll du benutzt, die müssen sogar austauschbar sein _ohne_ das du in Schicht 7 irgendwwas davon merkst.

    Wie gesagt, ist nur so ein Bauchgefühl...



  • Ich muss aber in meiner Applikation ein Timeout angeben, so warte ich ja *ewig* auf die Daten...



  • Nein den wenn die Verbindung unterbrochen wird (nur dann hast du ja scheinbar Probleme) bekommst du das von Windows mitgeteilt .



  • Jochen Kalmbach schrieb:

    Ich muss aber in meiner Applikation ein Timeout angeben, so warte ich ja *ewig* auf die Daten...

    Unix-Tom schrieb:

    Nein den wenn die Verbindung unterbrochen wird (nur dann hast du ja scheinbar Probleme) bekommst du das von Windows mitgeteilt .

    ganz so ist es nicht. angenommen dein socket wartet auf daten, hat aber selber gerade nichts zum senden und dann zieht jemand das netzwerkkabel ab. sowas wird nicht bemerkt (naja, der ethernet driver könnte den netzausfall bemerken und die sockets benachrichtigen, aber eben nur 'könnte').
    man kann natürlich mit der socket-option SO_KEEPALIVE was dagegen tun, aber ich glaube der default time-out dabei ist 2 stunden (inaktivität). ich weiss nicht, ob man das irgendwo verstellen kann. 🙂



  • In Fällen wo vor der Unterbrecchung "Windstille" war kann es wirklich ziemlich lange dauern bis der Stack was davon mitbekommt.
    In Fällen wo der Stack aber z.B. weiss dass noch etwas ankommen sollte (weil z.B. ein Paket "zwischendrinnen" gefehlt hat), oder man selbst etwas versenden will funktioniert es "akzeptabel".

    Alles in allem ist es für einen Server wohl immer die richtige Wahl selbst Timeouts zu implementieren. Was am grundsätzlihen Problem - und vor allem aucch der Lösung - natürlich nix ändert, nur dass man den Socket dann selbst zudreht bevor man einen "connection reset by peer" oder ähnliches bekommen hat.


Anmelden zum Antworten