Trouble sending file over 100mb with Indy Sockets

Hi people,

I'm having trouble when I tried to send one file with size over 100 mb with Indy TCP Sockets.

The code used are this:

Client:

  vSize := tcpClient.ReadInteger;
  if vSize > 0 then
  begin
    vFile:= 'c:\test_file.xyz';
    fStream := TFileStream.Create( vFile, fmCreate );
    try
      while tcpClient.Connected do
        tcpClient.ReadStream( fStream, -1, True );
      //tcpClient.ReadStream( fStream, vSize, False ); //same problem occur
    finally
      FreeAndNil(Stream1);
    end;
  end;

Server:

  vFile := 'c:\file_over_100mb.xyz';
  if FileExists( vFile ) then
  begin
    fStream := TFileStream.Create( vFile, fmOpenRead or fmShareDenyNone );
    try
      AThread.Connection.WriteInteger( fStream.Size, False );
      AThread.Connection.OpenWriteBuffer;
      AThread.Connection.WriteStream( fStream, True, False, fStream.Size );
      AThread.Connection.CloseWriteBuffer;
      AThread.Connection.Disconnect;
    finally
      fStream.Free;
    end;
  end
  else
    AThread.Connection.WriteInteger( 0, False );


This code works fine with files of 5, 10 or 20 mb....

Thanks...
LVL 2
alijuniorAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

2266180Commented:
hm... I tried the code with a small file and it's not working properly (delphi 7, indy 9) meaning that the integer is not sent through correctly because you do:

 AThread.Connection.WriteInteger( fStream.Size, False );
and then
 vSize := tcpClient.ReadInteger; (defaults to true) ;)

next thing will probably bne that 100 mb = 100 * 1024*1024 cannot be represented on an integer,, can it now :)

so I suggest using writln and readln and converting from and to int64.

but still you have the issue of overloading your memory. I did a test and the memory of my app went way up, also almost freezing my pc.

so what I suggest is uding a packet based protocol which you define and sending small chunks. an easy example would be (some pseudocode):

while file available do
begin
  size=readblock(file,buffer,buffersize);
  writecardinal(size);
  writebuffer(buffer);
end;

cheers

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
alijuniorAuthor Commented:
Hi ciuly...

I solve that as follows:

procedure v480_tcpSendFile( tcpConnection : TIdTCPServerConnection; vStream : TStream; cChunk : Integer = 1024 );
var mStream : TMemoryStream;
    vChunk,
    vSize : Integer;
begin

  vSize := vStream.Size;
  tcpConnection.WriteInteger( vSize );

  if vSize > 0 then
  begin
    tcpConnection.WriteInteger( cChunk );
    vStream.Seek( 0, soBeginning );
    mStream := TMemoryStream.Create;
    try
      repeat

        if vSize - vStream.Position >= cChunk then
          vChunk := cChunk
        else
          vChunk := vSize - vStream.Position;

        mStream.Clear;
        mStream.CopyFrom( vStream, vChunk );
        mStream.Seek( 0, soBeginning );

        tcpConnection.OpenWriteBuffer;
        tcpConnection.WriteStream( mStream, True, False, mStream.Size );
        tcpConnection.CloseWriteBuffer;

      until vStream.Position = vSize;

    finally
      mStream.Free;
    end;
  end;

end;

procedure v480_tcpRecvFile( tcpClient : TIdTCPClient; vStream : TStream );
var mStream : TMemoryStream;
    vSize : Integer;
    vChunk : Integer;
begin

  vSize := tcpClient.ReadInteger;
  if vSize > 0 then
  begin
    vChunk := tcpClient.ReadInteger;
    mStream := TMemoryStream.Create;
    try
      repeat
        mStream.Clear;
        tcpClient.ReadStream( mStream, vChunk, False );
        mStream.Seek( 0, soBeginning );
        vStream.CopyFrom( mStream, mStream.Size );

        if vSize - vStream.Position < vChunk then
          vChunk := vSize - vStream.Position;

      until vStream.Size >= vSize;
    finally
      mStream.Free;
    end;
  end;

end;
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.