![]() |
Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Community,
ich versuche seit letzter Woche einen TsslWSocket und einen TsslWSocketServer miteinander kommunizieren zu lassen. Ziel ist eine langzeitstabile Verbindung zwischen einem TCP-Client und einem TCP-Server, die mit TLS1.3 abgesichert ist. Nach einigen Minuten Laufzeit bricht die Datenübertragung jedoch ab. Es gibt einen ClientThread und einen ServerThread. In der jeweiligen Execute-Methode erzeuge ich den Socket und initialisiere ihn, rufe Listen (Server) bzw. Connect (Client) auf und lasse den Thread dann die MessageLoop ausführen. Nach erfolgreichem SSL-Handshake sendet mein Client 128KB große Datenpakete an den Server. Dort kommen sie auch an, TwSocketClient.onDataAvailable wird getriggert, die Bytes lassen sich dort mit TwSocketClient(Sender).Receive(pBuffer...) einlesen. Wenn der Server 128KB empfangen hat, sende er ein ein "ACK"-Paket an den Client (Den AnsiString "ACK", 3 Bytes). Wenn der Client ein Paket empfängt, sendet dieser erneut 128KB Daten. Dieses Spiel klappt einige tausend, manchmal auch einige zehntausend Male, bis dann TwSocketClient.onDataAvailable plötzlich nicht mehr aufgerufen wird. Es gibt kein OnSessionClosed, kein onError, kein onException und auch kein onBgException, daß auf ein Problem hindeuten würde. Offenbar ist das Problem auf Client-Seite: Ein mitlaufendes Wireshark zeigt als letztes ein [ACK]-Paket vom Server zum Client. Weitere Clicks auf den "Manual Send"-Button führen zu keinen weiteren Zeilen im Wireshark Log. Wenn dieser Zustand erreicht ist (eben nach etwa 4900 Paketen, beim Versuch zuvor nach etwa 590 Paketen) kann sich ein anderer Client problemlos mit dem Server verbinden. Ich will nicht ausschliessen, daß der Fehler bei mir liegt, bzw. nehme das sogar an, ich habe aber überhaupt keine Idee, was ich falsch machen könnte... Ist es vielleicht nicht ok, aus einem anderen Thread zu senden? Aber wie soll das sonst gehen, wenn der ClientThread nur noch die MessageLoop ausführt und somit selbst nicht senden kann? Gleichzeitiges Web-Browsen führt schneller zum Problem. Wenn ich mir irgendwelche Webseiten anschaue dauert es meist keine halbe Minute bis zum Problem. Anhängend ist mein Testprojekt. Mich würde mal interessieren, ob ihr dasselbe Problem beobachtet und ob jemand eine Vermutung hat, woran es liegen könnte... Das Projekt ist vollständig, im Win32-Ordner ist auch das zum Testen verwendete Zertifikat enthalten... Benutzung: Eigene IP-Adresse eingeben, auf den Button "btCreateStart" drücken, dann auf den Button "btSendData Manual Send". Im Programmverzeichnis wächst nun die Datei "logICStest.log" an, bis das Problem auftritt... Schon mal vielen Dank im voraus... P.S: Habe auch schon versucht, nicht nach dem Empfang des ACK-Pakets zu senden, sondern zyklisch per Timer oder Thread. Kann man beides im Testprojekt mit Checkboxen wählen, das Resultat ist das gleiche. Das Problem tritt nicht nur bei TLS1.3 auf, auch mit TLS1.2. Ich glaube sogar, es taucht auch ohne Verschlüsselung auf, dauert nur länger... Die verwendeten Versionen: Delphi 10.4 Update 3, ICS 8.64, OpenSSL 1.1.1g |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Nach meinem Verständnis von TCP/IP ist es nicht dafür gedacht eine echte dauerhafte Verbindung herzustellen, sondern nur nach Bedarf. Wenn ein Client etwas einem Server mitteilen möchte, oder von einem Server Neuigkeiten erfahren will, muss er sich verbinden, die Daten senden/empfangen und die Verbindung beenden. Dies kann der Client einmal pro Tag/stunde/Minute/Sekunde machen. Wie der Anwender oder Entwickler es eben möchte. Aber eine Dauerhafte Verbindung ist nicht im Sinne der Datensparsamkeit und darum mMn nicht vorgesehen.
Bedenke bitte auch, daß der Client zwar eine riesige Zahl an Absenderports zur Verfügung hat, der Server aber nur einen. So lange ein Client mit einem Server verbunden ist, ist dieser Port belegt. Sherlock |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Hallo Sherlock,
Ich möchte einige wenige (1..20) Clients mit einem Server (im lokalen Netz) verbinden, der Server liefert Echtzeitdaten die die Clients visualisieren sollen. Hierzu sollen sich die Clients beim Server anmelden und die Verbindung halten. Klar kann es sein, das eine TCP-Verbindung mal abbricht, aber im lokalen Netz doch wohl eher selten. In der realen Anwendung soll der Server von sich aus Daten über die bestehende Verbindung an die Clients schicken, der Client pollt also nicht. Ich vermute, daß ich die ICS-Komponenten entweder nicht richtig benutze (wahrscheinlich) oder das es da einen Fehler gibt (eher unwahrscheinlich). Aber gehen muss das... Allein schon deshalb, weil der SSL-Handshake eine Ewigkeit dauert... Gruß, Oliver |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
|
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Hi Rollo,
Danke für die Antwort. "keepalive" wäre wohl das Stichwort, wenn die Verbindung disconnecten würde, weil über einen längeren Zeitraum keine Daten übertragen werden. Das ist aber nicht mein Problem. Der Client sendet irgendwann nicht mehr wenn
Delphi-Quellcode:
ClientSocket.Send(TWSocketData(@Text[1]), Length(Text));
aufgerufen wird. Text ist ein 128KB langer AnsiString mit "ABCDEFG...XYZABCDEFG...". Es gibt zuvor kein OnDisconnect o.ä. Gruß, Oliver |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Hallo Sherlock,
meine Anwendung macht aber genau sowas im lokalen Netz, auch mit ICS. => TCP/IP ist schon für dauerhafte Verbindungen gedacht! Dem Fragesteller sei noch der Tipp gegeben, dass es in der en.delphipraxis.net ein ICS spezifisches Unterforum gibt. Vielleicht mal dort fragen, da lesen sicher ICS Entwickler mit. Grüße TurboMagic |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Ach so, ganz vergessen:
Mein Test-Programm startet Client und Server auf demselben Rechner, Netzwerkkomponenten scheiden somit als Grund aus. Hätte ich vielleicht erwähnen sollen... :? @TurboMagic: Danke für die Info. Hab's gerade schon crossgepostet, mal sehen was da kommt... |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Hallo!
Wenn es auch etwas anderes sein kann, nimm mORMot. Wenn du nicht den Server pollen willst, nimm WebSockets. mORMot musst du nicht installieren, sondern nur die Bibliothekspfad in Delphi 7 - 10.4 setzen. Folgende Links sind hilfreich: ![]() ![]() ![]() Bis bald... Thomas |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Bei mir läuft ICS 8.64 + Delphi 10.4 P1-3 in der freien Wildbahn auf ein paar hundert Kisten mit tausenden Verbindungen/Tag. Es sind keine Probleme bekannt.
[[ Dass tcp nur für kurzeitige Verbindungen genutzt werden sollte halte ich für ein Gerücht ;-). Zu Windows 3.1 Zeiten wurden jeweils Verbindungen gekappt, über welche wenig oder keine Daten ausgetauscht wurden. Da du mit D10.4 rumspielst, ist Win3.1 als Zielsystem vom Tisch. ]] |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Wir haben hier auch seit langer Laufzeit einen mini-messenger mit ICS verwirklicht am laufen ohne probleme, 365/7/24.
Was sich hin und wieder abschießt sind die Clients aber nie der Server. Ob die Datenleitung qualmt oder Tagelang still seht, solange der Server mit "Listen" eingeschaltet ist, macht der sturr sein Ding. |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Zitat:
Das Stichwort könnte TcpNumConnections sein. Bitte mal die Suchmaschine Deiner Wahl damit füttern. Als Ansatz hier mal ein paar Links zu den Suchergebnissen: ![]() ![]() ![]() ![]() ![]() Das "Problem" zieht sich quer durch alle Windowsversionen, beginnend spätestens bei Windows NT. Schau Dir bitte auch mal die Einstellungen für die ![]() Über ein Ping vom Client auf den Server kannst Du das recht einfach herausfinden:
Code:
Den Wert hinter dem Paramter -l verkleinerst Du, bis die Ausgabe von Ping in etwa so aussieht:
ping -n 1 -l 2000 -f www.delphipraxis.net
Ping www.delphipraxis.net [138.201.18.17] mit 2000 Bytes Daten: Paket müsste fragmentiert werden, DF-Flag ist jedoch gesetzt. Ping-Statistik für 138.201.18.17: Pakete: Gesendet = 1, Empfangen = 0, Verloren = 1 (100% Verlust),
Code:
Statt
ping -n 1 -l 1472 -f www.delphipraxis.net
Ping www.delphipraxis.net [138.201.18.17] mit 1472 Bytes Daten: Antwort von 138.201.18.17: Bytes=1472 Zeit=20ms TTL=55 Ping-Statistik für 138.201.18.17: Pakete: Gesendet = 1, Empfangen = 1, Verloren = 0 (0% Verlust), Ca. Zeitangaben in Millisek.: Minimum = 20ms, Maximum = 20ms, Mittelwert = 20ms ![]() Prüf' bitte auch, ob bei allen (oder zumindestenst einem Teil) der Clients die Ergebnisse übereinstimmen. Die MTU kannst Du auch über die Registry "vereinheitlichen": ![]() Deine 128 kb Daten werden, bei einer MTU, wie in diesem Beispiel, auf 128 kb (-> 128 * 1024) / 1472 = 89,043478260869565217391304347826 Pakete, also 90 Pakete aufgeteilt. Wenn die Größe von 128 kb je Paket nicht zwingend ist, kannst Du sie so anpassen, dass sie immer ein Vielfaches der oben ermittelten Paketgröße (hier also 1472 * x) enthalten. Dadurch wird der "Aufwand" für den Datenaustausch zwischen Client und Server verringert. Aber das fiele dann implementierungstechnisch eher unter "Chromleiste", könnte aber dabei helfen, das Problem zu verkleiner, bestenfalls zu verhindern. Das Ganze hier muss also jetzt nicht zwingend "die Lösung" des Problems sein, kommt aber eventuell der Quelle des von Dir beobachteten "Phänomens" etwas näher. |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Ich glaube nicht, dass bei deinem geposteten Beispiel MTU oder TcpNumConnections eine Rolle spielen.
Du baust ja eine 1:1 und lokale Verbindung auf => MTU Wert ist so ziemlich egal und die eine tcp Verbindung, welche du aufbaust sprengt - ausser vielleicht bei Uralt Win 3.1 ;-) - kaum TcpNumConnections. Wenn ich dein Programm laufen lasse und die Verbindung aufbaue, anschliessend dein Fenster rumschubsen will, dann reagiert es bereits nach kurzer Zeit nicht mehr wie es sein sollte. (Ruckeln) Das deutet auf ein Problem mit der Windows Warteschlange hin. Du knallst mit deinem WM_LOG die Windowswarteschlange zu. Kommentiere mal in lib_simplelog.info() Zeile
Delphi-Quellcode:
aus.
// PostMessage(LogHandle, LogMessage, wParam(Logline), 0);
Wenn ich das bei mir tue, dann reagiert das Fenster wie es sein sollte und ich kann 100'000+ Pakete übertragen, ohne irgendwelche Probleme festzustellen. Zum Code: Du weisst ja sicher, dass ICS auch SendStr und ReceiveStr/ReceiveStrA kennt. Wahrscheinlich hast du bewusst send(), receive() gewählt. Du reagierst noch nicht auf mögliche Fehler. Bei einer direkten Verbindung ist in den meisten Fällen wohl "Neuaufbau und weiter..." der beste Weg. Spannend wird es, wenn dein Netzwerk von vielen Beteiligten aufgespannt wird und Daten über mehrere Wege von A nach B fliessen. |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Vielen Dank für die weiteren Ideen.
Ich habe mittlerweile einen Workaround gefunden, es lag daran, daß ich vom VCL-Thread aus über den ClientSocket gesendet habe, der ja dem TClientThread gehört. Ich habe jetzt von TSslWSocket eine neue Klasse abgeleitet, mit der Möglichkeit, sich aus dem ThreadContext des ClientThreads "zurückrufen" zu lassen. In dem Callback kann dann sauber gesendet werden. Damit habe ich jetzt keine Probleme mehr. Ich habe die Lösung in der englischsprachigen DP gepostet, siehe ![]() @Michael II: Das Weglassen das Loggings sorgt nur dafür, daß das Problem nicht so häufig auftritt, aber nach einigen zehn/hundertausend Paketen tauchte es bei mir auf... Ich verwende Send/Receive, weil ich eigentlich ein binäres Protokoll verwenden will, keine Strings. Fehlerbehandlung ist in dem Testprogramm noch kein bisschen drin... Ich wollte ja, das es crasht, wenn es Probleme gibt. @Delphi.Narium: Vielen Dank für deine ausführlichen Ideen. Im Testprogramm lese ich einfach nur die Bytes, zähle sie und schmeiße sie weg, in der richtigen Anwendung schreibe ich die gelesenen Bytes in einen Ringpuffer, die MTU ist somit egal. Das Protokoll ist so aufgebaut, das erst ein paar "Magic Bytes" kommen, dann die Nutzdatenlänge (Int64, 8 Bytes hintereinander weg) und dann die eigentlichen Daten. Der Ringpuffer hat eine Statemachine, die sich entweder im Zustand WarteAufMagic, WarteAufDataLen oder WarteAufNutzdaten befindet. Das geht schön schnell... |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Zitat:
OK super, hat's geklappt. Wenn du binäre Daten senden willst, dann teste doch mit #0#1#2#3....#255 und nicht mit ABC...Z :-D. Ich sehe (wie Angus) keinen Gewinn durch die Verwendung von Threads [aber wir sehen ja auch nur einen Test und nicht das fertige Produkt]. Hast du mal gemessen, wie der Datendurchsatz mit deinem Threads Konstrukt und wie er ohne ist? MTU ist zwar für dein Beispiel mit grossen Paketen egal. Wenn du aber auch sehr kleine Datenpakete (<MTU Wert) immer sofort senden musst/willst (zum Beispiel bei einem Spiel oder Börsensoftware), dann lohnt sich ein Blick auf ComponentOptions -> wsoTcpNoDelay. Aber das weisst du ja sicher bereits :-D. |
AW: Stabile TCP-Verbindung mit ICS, ich kriegs nicht hin...
Programmintern mag die MTU egal sein.
Sie ist für die Kommunikation der Rechner untereinander (auf Netzwerk- / Protokollebene) von Bedeutung. Und wenn die Kommunikation dort nicht sauber läuft, kannst Du in Deinem Programm Workarounds machen, soviel Du willst. Solange der Netzverkehr nicht sauber und stabil läuft, erreichst Du allenfalls eine Verschiebung / Verzögerung / Verlagerung des Problems. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz