Can I get the size of the bytes that are in a Indy TCP connection buffer but are not yet transmited?

394 Views Asked by At

I want to send some (big) files over an internet connection at the maximum possible speed, using Indy TCP. I have writen a simple app to test how Indy TCP Client-Server connection works.

What I discovered is that:

  • all writes to the socket happens instantly
  • even if Disconnect after I write, the data is still received on the other side, if it is read
  • the data can have any size; I wrote 100 MB and I received every bit.

So it means that there is a transmission buffer on the socket that is writen to. And it looks like it can have any size... If I write a large amount of data (let's say 100 MB), I think it is not transmited in a single operation, but in small chuncks (let's say 1 MB). So, as the data is transmitted, that buffer shrinks until it reaches zero, when all data is transmitted. What I need is the length of that buffer at any time, to know when it needs to be filled, so I cand write continuously without thaking up the whole computer memory.

I don't know if what I wrote here makes sense... If not, please tell me to delete the question and ask a more general question. What I want in the end, is to send a file through a Indy TCP connection at the highest speed possible (meaning asynchronous), but with a progress bar and a cancel button.

This is the test app:

procedure TClient.Execute;
var Cmd: Cardinal;
    Txt: String;
    Buff: TIdBytes;
    Size: Integer;
begin
 Size:= 5000000;
 SetLength(Buff, Size);
 Buff[0]:= 33;
 Buff[Size-1]:= 55;

 Client.Connect;
 Cmd:= 1234;
 Client.Socket.Write(Cmd);
 Client.Socket.Write(Size);
 Client.Socket.Write(Buff);
 Txt:= 'client finished transmision';
 SendMessage(RWnd, WM_USER, WPARAM(@Txt), 0);
 Client.Disconnect;
 Txt:= 'client disconected';
 SendMessage(RWnd, WM_USER, WPARAM(@Txt), 0);
end;

procedure TForm1.ServerExecute(AContext: TIdContext);
var Cmd: Cardinal;
    Mess: String;
    Buff: TIdBytes;
    Size: Integer;
begin
  Mess:= 'Server ready';
  SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);

  Cmd:= AContext.Connection.Socket.ReadUInt32;
  Mess:= 'Server receive command';
  SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);

  if Cmd = 1234 then begin
   Size:= AContext.Connection.Socket.ReadInt32;
   Sleep(4000);
   Mess:= 'Server start reading';
   SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
   AContext.Connection.Socket.ReadBytes(Buff, Size);
   Mess:= IntToStr(Buff[0]) + ' / ' + IntToStr(Buff[Size-1]);
   SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
  end;

  Mess:= 'Server closed connection';
  SendMessage(Handle, WM_USER, WPARAM(@Mess), 0);
end;
0

There are 0 best solutions below