![]() |
Multi Socket Transfer
Hallo Delphi Programmierer.
Ich habe 2 Anwendungen die eine läuft als Client und die andere als Server. Dabei benutze ich die TClient/TServer Socket. Um mehrere Dateien gleichzeitig zu senden erstelle ich zur laufzeit immer wieder einen Client der die entsprechende Datei dann sendet. Wenn ich z.b 2 oder 3 Dateien gleichzeitig versende funktioniert alles gut. Aber sobald es dann mehr als 4 Dateien sind die gleichzeitig gesendet werden, passiert es dann das die empfangenen Dateien manchmal fehlerhaft sind. Zum Testen werden meistens Bilder verwendet und die haben dann fehler wenn man sie anschaut. Sobald ein neuer Client erstellt wird sendet dieser die Datei so.....
Delphi-Quellcode:
FileHandle := CreateFile(pchar(File_Pfad),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
FileSize := GetFileSize(FileHandle,nil); SendData(Socket,'FileTransfer|OpenFile|' + inttostr(FileSize)); while FileNotEnd do begin if FileSize - 4096 > 0 then begin SetLength(Data,4096); ReadFile(FileHandle,pointer(Data)^,4096,BytesRead,0); FileSize := FileSize - 4096; SendData(Socket,'FileTransfer|WriteFile|' + Data); Sleep(10); end else begin SetLength(Data,FileSize); ReadFile(FileHandle,pointer(Data)^,FileSize,BytesRead,0); SendData(Socket,'FileTransfer|WriteFile|' + Data); Sleep(10); FileNotEnd := False; SendData(Socket,'FileTransfer|CloseFile'); CloseHandle(FileHandle); end; end;
Delphi-Quellcode:
Sende ich zu schnell so das die Sockets nicht hinterher kommen?
procedure SendData(Socket: TClientSocket; Data: string);
var Temp: ansistring; begin while (Length(Data) > 0) and (Socket.Connected) do begin Temp := AnsiString(Copy(Data,1,4096)); Delete(Data,1,4096); repeat Sleep(5); until Socket.SendBuffer(pointer(Temp)^,length(Temp)) <> -1; sleep(5); end; end; Komisch ist das es ersst auftritt sobald ich mehr als 4 Bilder Gleichzeitig versende. Danke schonmal im voraus. |
AW: Multi Socket Transfer
Das Bild, das beim senden von 4 oder mehr Probleme macht funktioniert, wenn du es einzeln sendest? Merkwürdig.
Generell würde ich ein Bild oder eine andere Datei nicht in einen String laden und dann als AnsiString casten, dass kann dir Steuerzeichen in der Datei zerstören. Besser wäre hier die Datei zB als Base64 zu kodieren, oder direkt mit Bytes(oder Bytestream) zu arbeiten, ohne diese in einen String zu schreiben. |
AW: Multi Socket Transfer
Ich weiß ja nicht wie weit dein Projekt fortgeschritten ist. Habe mich selbst mit der Client-Server-Programmierung beschäftigt und quasi ALLE Socket-Componenten getestet. Hängengeblieben bin ich bei
![]() Vielleicht wäre das einen Versuch - auch für die Zukunft - wert. |
AW: Multi Socket Transfer
wie willst du wissen, ob du eventuell zuschnell zuviel sendest, wenn du das nirgends abfragst und/oder auswertest ?!
- Ich garantiere dir, über eine langsame WLan oder INet Verbindung zu einem Server im INet bekommst du "so" schon ab der ersten Dateiübertragung Probleme! - auch wenn es mit AnsiString als Datenpuffer gerade (noch) funktioniert, man macht es nicht. Nimm "TBytes" und bei Casts nie typenlose "Pointer" sondern immer den passenden Typ, hier z-B. "PByteArray" - über Sockets ist die Mischung aus StringCMDs und folgenden Binärdaten durchaus nix ungewöhnliches, nur macht man das besser in zwei Aufrufen wo der ersten im Klartext ankündigt, was dann binär kommt... besser ist es dort auch den Offset und die erwartete Länge vorab mit zu geben und erst dann die Binärdaten zu schicken - noch besser wir es, wenn man sich selbst synchronisiert, in dem der Empfänger den Empfang der Daten durch rücksenden des empfangenen Blocks (hier also des StartOffsets) "quittiert" und man erst dann den nächsten Datenblock in den Socket zum Senden reinschreibt. - sicher wird es, wenn der Empfänger bei seiner Quiitung noch eine Checksumme über die empfangenen Daten zurück schickt, welche der Sender vergleicht und bei Fehler den Datenblock z.B. nochmal wiederholt - wichtig ist irgendein Sync!... man soll und darf den OS-TCPIP-Stack nicht als quasi unendlich großen Datenpuffer mißbrauchen! |
AW: Multi Socket Transfer
Die wichtigste Frage wäre, ob du die Sockets im "blocking" oder "non-blocking" Mode verwendest. Ich vermute, dass letztere Variante der Fall ist, denn nur dann hast du die von mensch72 beschriebenen Probleme. Im blocking Mode blockiert der
![]() ![]() Zitat:
Zitat:
![]() ![]() ![]() ![]() Etwas komplizierter ist es bei "non-blocking" Sockets. Hier muss die Rückgabe von ![]() Zitat:
Zitat:
Zitat:
Zitat:
|
AW: Multi Socket Transfer
mir ist die vom Layer bei TCP hier schon garantierten vollständigen und gesicherten Übertragung (im gegensatz z.B. zu UDP) durchaus klar und auch der Unterschied zw. "blocking"(hoffentlich Thread basiert) oder "non-blocking"(hoffentlich eventbasiert) ist bekannt:)
Aber wenn ich den ersten Quelltext hier sehe, glaube ich das man ohne viel Nachdenken und Zeitaufwand es mit einer resultierend durch Übertragungszeit und Datenoverhead verlangsamenden eigenen logischen Quittung als Einsteiger leichter hin bekommt, als wenn man alles nur auf Basis der SocketStates(error, busy oder ready) verarbeiten und strukturieren soll. -> Hier möchte jemand mehr Funktions&Datensicherheit, also kann er nach meiner Einschätzung&Erfahrung die so mit wenig (Lern)Aufwand weiter mit seinen aktuellen Mitteln reicht einfach erreichen. -> Und ja, auch wenn es dem allgemeinem Ansatz der "eh schon per Layer gesicherten) Übertragung per TCP wiederspricht, ich finde logische Blockquittungen seitens des Empfängers sinnvoll, wenn dieser damit anzeigt das er die Daten erfolgreich empfangen UND VERARBEITET hat(in dem Fall Block erfolgreich auf HD gespeichert). => Möge der Fragende selbst entscheiden ob er sich weiter voll auf den Stack und dann nötige Auswertung von dessen States&Errors verlässt, oder sich weiter um nichts kümmert und es mit einer einfachen zusätzlichen eigenen Quittung selbst löst(und sein Ausgagsproblem so dann eben umgeht). Da ich falsches Verhalten des Sockets ausschließe, wäre eine mögliche "non blocked" Erkläung für beschriebenen Effekt: der Socket hat beim Send die per Pointer übergebenen Daten nicht selbst dupliziert, sondern überträgt diese direkt ... heißt wenn dies in 10ms wie hier programmiert nicht fertig, würden durch den nächsten FileRead die Daten mit neuen Werten überschrieben. Klar, wenn es ein "blocked Socked ist, kann&darf der garnicht zurückkommen, bevor nicht alle Daten "bestätigt" versendet sind... aber warum verwendet hier dann einer noch ein Sleep(10)???... ist es eventuell eben doch eine NonBlocked Übertragung??? => Genau weil da wo ich bin sich NIEMALS jemand um sowas Gedanken machen will(schon garnicht beim Lesen fremder Quelltexte), gilt bei uns die goldene Regel: wir quittieren alles logisch und sei es über einen 2. Kanal (z.B. anderer Port,UDP,...) OffTopic: Nach Layerdefinition garantiert der Stack das TCP "100% sicher" ist... eventuell ist es unter Linux so aber Windows mag es reproduzierbar garnicht, wenn ich zuviel parallel mit einmal in/an den Stack gebe. Wenn ich optimale Übertragung fast ohne Overhead will, bleibe ich mit meinem PayLoad knapp unter der aktuell verfügbaren FrameSize im Netzwerk. Leider programmiere ich auch netzwerkfähige Embedded Microcontroler... da gibt es dann zwar auch einen TCP-Socket, nur der hat sehr oft seine physikalischen Grenzen(z.B. DMA-SpeicherpufferGröße)... daher quäle ich diesen nicht und übertrage nicht mehr als in ein Paket was in den internen Puffer passt und etwas unter der NetzwerkFrameSize liegt. Dann warte ich bis es die Gegenstelle "logisch" quittiert. Nur so funktioniert es problemlos von 8..64Bit und im Speed von GPRS bis GigaBit, auch wenn man per Definition sich bei TCP-Sockets um sowas selbst garnicht mehr kümmern soll:) |
AW: Multi Socket Transfer
Zitat:
Die Lösungen wären also: * Dateilänge vorab senden * oder: Base64 Encoding verwenden und ein Null-Endebyte senden Das es dennoch funktioniert, liegt daran dass der Server-Code beim Ausbleiben von Daten 'optimistisch' annimmt es sei das Ende der Datei erreicht ;) |
AW: Multi Socket Transfer
..."Woran erkennt der Server das Ende der Datei"...?
=> steht doch oben im Quelltext... zum Schluss wird ein "CloseFile" als logische SteuerInformation an den Client geschickt... ist zwar für den Client nicht überprüfbar ob er alles ahat, aber es funktioniert wenn alles gut geht so durch aus:) Eine "Base64" Übertragung gibt 25% Overhead... muss nicht sein wenn man sich wie aktuell auf den TCP Stream verlässt oder eben besser doch Offset&Länge noch als SteuerInfo mit überträgt. |
AW: Multi Socket Transfer
Zitat:
p.s. der Server sendet die Dateien 'gleichzeitig'. Werden mehrere Threads erzeugt? Wie sieht der Code dazu aus? |
AW: Multi Socket Transfer
Zitat:
Zitat:
Zitat:
Zitat:
![]() ![]() ![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:49 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 by Thomas Breitkreuz