Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Dateien mit Indy versenden, Problem mit großen Dateien (https://www.delphipraxis.net/187175-dateien-mit-indy-versenden-problem-mit-grossen-dateien.html)

MuTzE.Y85 4. Nov 2015 08:33

Dateien mit Indy versenden, Problem mit großen Dateien
 
Hi Leute,

ich habe mir ein kleines Tool geschrieben um Dateien übers Internet auszutauschen.
Das funktioniert soweit auch erstmal bis auf das Problem, dass bei "großen" Dateien (z.B. bei knapp 400 MB)
die Meldung kommt: "Zu wenig Arbeitsspeicher".

Kompiliere ich die Anwendung als 64-bit funktioniert es ohne Probleme.
Zur Info, das System hat 16 GB RAM.

Kann mir jemand sagen, wo ich den Fehler mache?
Bei wirklich großen Dateien hätte ich es ja verstanden aber schon bei 400 MB?


Vielen Dank schonmal!



Hier mal der Quellcode:

CLIENT
Delphi-Quellcode:
procedure TForm1.SendFile(aFileName: String);
var
  fs: TFileStream;
begin
  with IdTCPClient do
  begin
    fs := TFileStream.Create(aFileName, fmOpenRead or fmShareDenyWrite);
    try
      // Dateiname übertragen
      IOHandler.WriteLn('FT_FILENAME:' + ExtractFileName(aFileName));
      IOHandler.WriteBufferOpen;
      try
        // Datei übertragen
        IOHandler.Write(fs, 0, True);
        IOHandler.WriteBufferClose;
      except
        IOHandler.WriteBufferCancel;
        raise;
      end;
    finally
      fs.Free;
    end;
  end;
end;

SERVER
Delphi-Quellcode:
procedure TForm1.IdTCPServerExecute(AContext: TIdContext);
var
  fs: TFileStream;
  CommandString: String;
begin
  AContext.Connection.IOHandler.CheckForDataOnSource(10);
  if not AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    // Befehl empfangen
    CommandString := AContext.Connection.IOHandler.ReadLn;

    if CommandString.StartsWith('FT_FILENAME:') then
    begin
      // Dateiname auslesen
      CommandString := Copy(CommandString, 13, CommandString.Length - 12);
      fs := TFileStream.Create('D:\TEST\' + CommandString,
        fmCreate or fmShareExclusive);
      with AContext.Connection do
        try
          // Datei empfangen
          IOHandler.ReadStream(fs, -1, False);
        finally
          fs.Free;
        end;
    end;
  end;
end;

Perlsau 4. Nov 2015 11:57

AW: Dateien mit Indy versenden, Problem mit großen Dateien
 
Vermutlich ist zu wenig zusammenhängender Speicher unter 32-bit verfügbar. Beim Auswerten der Logfiles meines Webservers (1&1) ist mir aufgefallen, daß zahlreiche Clients Dateien stückweise herunterladen werden (Responce-Code 206), wenn die ganze Datei eine gewisse Größe überschreitet. Wie das genau vonstatten geht, vermag ich derzeit nicht zu beschreiben, aber vielleicht genügt dir dieser Hinweis, um eine Lösung für dein Problem zu entwickeln (Stichwort Teil-Download). Wenn ich das richtig beobachte, machen das die gängigen Browser auch nicht anders, denn beim Download erscheint immer eine Temp-Datei, die nach & nach größer wird.

Bambini 4. Nov 2015 14:08

AW: Dateien mit Indy versenden, Problem mit großen Dateien
 
Zitat:

Zitat von MuTzE.Y85 (Beitrag 1320477)
Delphi-Quellcode:
      IOHandler.WriteBufferOpen;
Delphi-Quellcode:
        IOHandler.WriteBufferClose;

Den WriteBufferOpen/Close darf nicht verwendet werden, das sonst alles erst über den Buffer gehen muss, bevor versendet wird. Das will man bei großen Daten genau vermeiden.

MuTzE.Y85 4. Nov 2015 16:05

AW: Dateien mit Indy versenden, Problem mit großen Dateien
 
Hey super! Genau das war das Problem :)

Danke euch!

himitsu 5. Nov 2015 10:14

AW: Dateien mit Indy versenden, Problem mit großen Dateien
 
Dein RAM, bzw. der virtuelle Arbeitsspeicher deines Prozesses/Programms, ist fragmentiert.
Überall liegen die EXE, DLLs und sonstiges Zeug im Speicher.

Bei 32 Bit hast du (standardmäßig) nur knapp 2 GB RAM zur Verfügung und dann versuche da mal ein großes zusammenhängendes freies Stückchen zu bekommen.
Mehr als 700 MB sind fast nie mäglich und ab 350 MB wird es ganz schön schwer.

MuTzE.Y85 5. Nov 2015 18:30

AW: Dateien mit Indy versenden, Problem mit großen Dateien
 
Und wenn ich WriteBufferOpen weglasse stückelt er es vonn alleine ja?

Kann das WriteBufferCancel eigentlich nicht auch raus nach dem except?

Bambini 6. Nov 2015 08:37

AW: Dateien mit Indy versenden, Problem mit großen Dateien
 
Zitat:

Zitat von MuTzE.Y85 (Beitrag 1320717)
Und wenn ich WriteBufferOpen weglasse stückelt er es vonn alleine ja?

Ja, Es wird dann in den Buffergrößen verschickt. Default ist 32 kB.

Zitat:

Zitat von MuTzE.Y85 (Beitrag 1320717)
Kann das WriteBufferCancel eigentlich nicht auch raus nach dem except?

Ja.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:39 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz