LabVIEWForum.de
Dateiempfang unbekannter Größe über TCP - Druckversion

+- LabVIEWForum.de (https://www.labviewforum.de)
+-- Forum: LabVIEW (/Forum-LabVIEW)
+--- Forum: LabVIEW Allgemein (/Forum-LabVIEW-Allgemein)
+---- Forum: Datenkommunikation (/Forum-Datenkommunikation)
+---- Thema: Dateiempfang unbekannter Größe über TCP (/Thread-Dateiempfang-unbekannter-Groesse-ueber-TCP)

Seiten: 1 2


Dateiempfang unbekannter Größe über TCP - TpunktN - 02.02.2021 15:07

Servus zusammen,

ich verzweifel hier gerade.. Ich bin dabei eine Software von ILA per Remote zu steuern, es handelt sich dabei um ein Laser-Doppler-Velocimeter.
Soweit bekomme ich das Meiste hin, auch wenn die Doku dazu recht sparsam ist, kann ich aktuell per try and error immer mal wieder testen und direkt vergleichen/korrigieren.

Problem habe ich bei der "Binary Data Transfer" von Messdaten, da werden ganze Dateien übertragen, unbekannter Größe (aktuell ist die Datei ca. 33 KB groß).
Anbei mal ein Zusammenschnitt, wie diese Datei aufgebaut ist, wobei '...' mehr Daten sind.
Code:
TransferedFileName;0;C:\LDA_DATA\ProjectA\ProjectA_a.ldv<CRLF>
1 0.000 0.000 0.000 6.602446e+00 5.841750e-01 6.603106e+04 22696 9.999000e+01 1.320417e+03 5.537910e+01 1.320549e+07 22696 9.999000e+01 07/23/20 13:53:35 07/23/20 13:53:55
...
276 0.000 0.000 0.000 0.000000e+00 0.000000e+00 0.000000e+00 0 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0 0.000000e+00 02/02/21 07:41:07 02/02/21 07:41:17
FinishSendFile<CRLF>
TransferedFileName;0;C:/LDA_DATA/ProjectA/ProjectA_a.csv<CRLF>
Nr.;X[mm];Y[mm];Z[mm];Vx[m/s];Tux[%];fDx[Hz];NrBurstsx;Fringe_dx[um];Vy[m/s];Tuy[%];fDy[Hz];NrBurstsy;Fringe_dy[um];Start;End;Vz[m/s];Tuz[%];fDz[Hz];NrBurstsz;Fringe_dz[um];Va[m/s];Tua[%];fDa[Hz];NrBurstsa;Fringe_da[um]
1;0.000;0.000;0.000;6.602446e+00;5.841750e-01;6.603106e+04;22696;9.999000e+01;1.320417e+03;5.537910e+01;1.320549e+07;22696;9.999000e+01;07/23/20 13:53:35;07/23/20 13:53:55
...
276;0.000;0.000;0.000;0.000000e+00;0.000000e+00;0.000000e+00;0;0.000000e+00;0.000000e+00;0.000000e+00;0.000000e+00;0;0.000000e+00;02/02/21 07:41:07;02/02/21 07:41:17
FinishSendFile<CRLF>
<CRLF> das sind die einzigen Zeilen mit \r\n als Abschluss, darauf zu warten, bei unbekannter Dateigröße, sehe ich aber als riskant.
Es sind 2 Dateien, starten mit
"TransferedFileName";0; <Dateipfad> (wobei die 2te Datei / die erste \ Ordner trennt, das habe ich schon abgefangen)
<Daten>
"FinishSendFile"

Meine Versuche waren:
-kleine Häppchen abfragen und Zeilenweise in die Datei schreiben, dabei kam mir aber der time out vom TCP lesen immer weider in den Weg. Entweder hat er alles ausgebremst oder ich habe nicht alles gelesen.
-Größere Häppchen lesen und direkt wegschreiben, da hat er dann teilweise die nächste Datei nicht erkannt (Endmarker abgeschnitten? oder Daten kommen zu langsam rein?)
-(Als Bild anbei) große Datenmengen lesen und wegschreiben. Da hatte ich dann Schwierigkeiten mit den Bedingungen für die nächste Datei, Daten kamen zu langsam rein
und mein Kopf ist nun voll (und ich bitte hier um Hilfe) -.-'

Das ganze ist mit DQMH geschrieben, im Case "Next File" wird geprüft ob "TransferedFileName" anliegt und übergibt dann neue Parameter zu diesem Case, wenn nicht, ist er fertig.
Es gibt noch 2 andere Dateien, die empfangen werden können, die übertragen je nur eine Datei.
Ich würde gerne wenig Zeit mit der Datenübertragung verschwenden, also lange timeouts vermeiden.

Welchen schritt würdet Ihr gehen, gibt es eine (einfache) Möglichkeit zu prüfen ob da noch was am Port kommt?
Ich habe TCP bisher nur für ASCII Befehle benutzt mit CRLF als Modus.

Ich bin wie immer für jeden Tipp dankbar.
Timo


RE: Dateiempfang unbekannter Größe über TCP - jg - 02.02.2021 16:56

Hallo Timo,

CR-LF ist das Abschlusszeichen der Daten, die per TCP/IP empfangen werden sollen?! Das ist doch WUNDERBAR, schließlich ist das einer der Modi bei TCP-Read.

Zitat aus der Hilfe von TCP-Read:
Zitat:CRLF—Waits until all bytes you specify in bytes to read arrive or until the function receives a CR (carriage return) followed by a LF (linefeed) within the number of bytes you specify in bytes to read or until timeout ms runs out. The function returns the bytes up to and including the CR and LF if it finds them in the string.

Hier eine kleine Anregung, wie eine Lese-Prozedur aussehen könnte (ohne Fehlerbehandlung, die muss hier noch dazu, und ein Maximal-Timeout, nicht dass das eine Dauerschleife wird):

[attachment=61607]

Gruß, Jens


RE: Dateiempfang unbekannter Größe über TCP - Martin.Henz - 02.02.2021 17:34

Hallo Timo,

Zitat:<CRLF> das sind die einzigen Zeilen mit \r\n als Abschluss, darauf zu warten, bei unbekannter Dateigröße, sehe ich aber als riskant.

wir ging es wie dem Jens. Wegen dem CRLF ist das doch super einfach und warum sollte das nicht funktionieren - oder was meinst du, wie z.B. eine E-Mail übertragen wird. Alles mit CRLF ...


RE: Dateiempfang unbekannter Größe über TCP - TpunktN - 03.02.2021 07:54

Danke,

ich habe keine Ahnung von TCP Programmierung, auch meine jahrelange LAN-Party Erfahrung hilft nicht bei den Abschlusszeichen im Protokoll. Big Grin
Meine Bedenken sind die, die Datei wird auf dem Host-PC nie gelöscht und immer weiter erweitert und irgendwann größer als der Buffer am TCP Port (wie groß ist der eigentlich?)
Schneller als der Host-PC es rausschickt werde ich es nicht empfangen, um das Programm nicht zu blockieren wollte ich immer wieder abfragen und habe dann angst, das (nach Jahren) die Datei den Speicher voll schreibt und ich Out of Memory laufe -.-' Deswegen gleich wegschreiben.

Ich möchte nicht wieder ein Programm schreiben nach dem Prinzip, "erstmal funktioniert das".
Oder sind meine Bedenken
-Port Eingang voll und
-RAM voll
-Modul ist dann erstmal blockiert
eher unwahrscheinlich?
Ich kann ja ne Fehlermeldung ausgeben, das die Datei gelöscht werden soll Big Grin


RE: Dateiempfang unbekannter Größe über TCP - GerdW - 03.02.2021 08:15

Hallo T.N,

Zitat:Meine Bedenken sind die, die Datei wird auf dem Host-PC nie gelöscht und immer weiter erweitert und irgendwann größer als der Buffer am TCP Port (wie groß ist der eigentlich?)
Wenn du beim TCPRead z.B. 16kB im Modus CRLF anfragst, dann stoppt die Leseroutine, wenn
1. 16kB empfangen wurden
2. ein CRLF enpfangen wurde
3. ein Fehler beim Lesen auftrat
Danach kannst du die empfangenen Daten wegschreiben und auf evtl. auftretende Fehler reagieren.

Wieso soll es ein Problem sein, eine "Datei auf dem Host-PC immer zu erweitern" (genügend große Festplatte vorausgesetzt)?
Wieso hast du Angst um einen TCP-Buffer?

Zitat:Ich kann ja ne Fehlermeldung ausgeben, das die Datei gelöscht werden soll
Du kannst programmatisch
1. die aktuelle Dateigröße abfragen
2. den freien Speicherplatz auf der Festplatte abfragen
Und danach kannst du programmatisch entscheiden, ob dein Programm den User über Speichermangel informiert oder einfach das Speichern einstellen soll…


RE: Dateiempfang unbekannter Größe über TCP - TpunktN - 03.02.2021 11:21

(03.02.2021 08:15 )GerdW schrieb:  Wenn du beim TCPRead z.B. 16kB im Modus CRLF anfragst, dann stoppt die Leseroutine, ...
Hab mir die verscheidenen Modi angeschaut und fand halt bei 'Immediate' den Vorteil, das er nicht wartet, sobald etwas anliegt.
Werde das mal mit CRLF ausprobieren, time out ist ja Fehler 56.
Danke für das Beispiel @jg. Das Endzeichen zu prüfen war 'nen guter Hinweis.

Zitat:Wieso soll es ein Problem sein, eine "Datei auf dem Host-PC immer zu erweitern" (genügend große Festplatte vorausgesetzt)?
Wie schnell ist die Datenübertragung im Binäreformat? Wenn ich da meine volle Gigabit-LAN Verbindung ausnutze ist das vermutlich kein Problem, wenn aber 15 Sekunden lang nach jedem Abfragen gewartet werden muss und das Programm in der Zeit nichts anderes macht, sehe ich das als nicht sinnvoll.
Zitat:Wieso hast du Angst um einen TCP-Buffer?
Weil ich die Eingangszahl schon mal auf maximum (I32) gesetzt habe und ne dauer Fehlerschleife produziert hab Big Grin Hätte ich mal lieber vorher nachgedacht...
War quasi als test, maximum lesen mit hohem timeout im CRLF Modus. Das aber stückchenweise machen, was ich ja schon mache, nur ohne CRLF, könnte deutlich einfacher sein.

Danke Euch, ich test das mal.
Timo


RE: Dateiempfang unbekannter Größe über TCP - Martin.Henz - 04.02.2021 09:29

Hallo Jens,

nimms mir nicht übel, aber es gibt einen Fall bei dem dein Beispiel nicht funktioniert.

Das Beispiel liest maximal 5000 Zeichen pro Iteration der While-Schleife. Wenn nun also die 5000 Bytes bei Iteration n erreicht sind und dies dummerweise mit dem CR endet, dann kommt erst bei der nächsten Iteration n+1 das LF Zeichen. Die Schleifenbedingung findet in diesem Fall jedoch das CRLR nicht und liest einfach weiter Daten vom Server.


RE: Dateiempfang unbekannter Größe über TCP - TpunktN - 04.02.2021 10:22

Es funktioniert jetzt mit den Vorschlägen deutlich besser, aktuellen Stand habe ich mal angehängt.
Bedenken habe ich aber für den Fall, den Martin erwähnt:
(04.02.2021 09:29 )Martin.Henz schrieb:  Das Beispiel liest maximal 5000 Zeichen pro Iteration der While-Schleife. Wenn nun also die 5000 Bytes bei Iteration n erreicht sind und dies dummerweise mit dem CR endet, dann kommt erst bei der nächsten Iteration n+1 das LF Zeichen. Die Schleifenbedingung findet in diesem Fall jedoch das CRLR nicht und liest einfach weiter Daten vom Server.

So ähnlich habe ich auch meine bedenken und versuche gerade das irgendwie abzufangen, zumal ich ein etwas längeren String lese (FinishSendFile\r\n).
Reduzieren kann ich das ja indem ich nur CRLF abfrage, ich denke aber eher darüber nach, eine kleine Kontrolle mit dem letzten (der schon geschriebene) Buffer zusammen zu machen und darauf zu entscheiden.
Sofern niemand eine bessere/fertige Lösung hat, versuche ich mich mal daran.

Danke, Timo


RE: Dateiempfang unbekannter Größe über TCP - Martin.Henz - 04.02.2021 12:32

Hi Timo,

ansattt "FinishSendFile\r\n" einfach "FinishSendFile\r\n$" nehmen. An Ende steht ja immer "\r\n", denn da wird dank CRLF Modus das einlesen immer abgebrochen. Eigentlich genügt "\r\n$" bereits.

Aber wieso liest du denn 524288 Bytes auf einmal ein ... und das auch noch mit einem timeout von 500ms?


RE: Dateiempfang unbekannter Größe über TCP - TpunktN - 04.02.2021 13:29

(04.02.2021 12:32 )Martin.Henz schrieb:  Eigentlich genügt "\r\n$" bereits.
Musste erstmal nachlesen was das $ bedeutet.
Mit dem ganzen String spare ich mir das rausfiltern im nachhinein, das "FinishSendFile" soll nicht in der Datei stehen.
tatsächlich ist der Buffer noch Relikt aus den vorherigen Versuchen (der sollte jetzt immer leer sein), werde ich aber noch brauchen um einen evtl. abgeschnittenen Endteil zusammenzusetzen und da bin ich gerade am experimentieren.
Zitat:Aber wieso liest du denn 524288 Bytes auf einmal ein ... und das auch noch mit einem timeout von 500ms?
Irgendetwas musste ich ja vorgeben und da ist mir nur 512 KB eingefallen Big Grin Weil MS Präsentation .. Bricht ja eh ab bei CRLF oder time out.
Und "nur" 500ms (ist in der zwischenzeit 1000ms), weil ich auch nicht ewig warten will, falls was schief geht. Ich hoffe einfach, dass nicht mein gesamtes Programm blockiert, nur weil die Datei noch übertragen wird.

Danke für die Kritik, sowas zu "rechtfertigen" hilft auch immer mal wieder um sich den Code auch bewusst nochmal anzuschauen.
Timo