Atozed Forums

Full Version: Simulating low bandwidth with TIdHTTP
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Pages: 1 2
Hi,

I need to simulate internet speed for testing purposes both client and server apps are on my dev machine. I use for this "TIdInterceptThrottler" component, it works fine during downloading or uploading the data but it still resolves the host very fast I want to slow down that too to the speed of my choice like as if the server is remote not on the same machine as the client.

Is there a trick that can be done to mimice that with indy components or whatever?

Thanks in advance, any help will be appreciated
Host resolution is handled by DNS, not HTTP.
(12-01-2020, 02:03 PM)kudzu Wrote: [ -> ]Host resolution is handled by DNS, not HTTP.

Sorry. What I meant is that the client still connects to host faster than the simulated speed as it is still on the same machine, while connecting to a remote server takes around a second or two.
(12-01-2020, 05:08 PM)Ahmed Sayed Wrote: [ -> ]Sorry. What I meant is that the client still connects to host faster than the simulated speed as it is still on the same machine, while connecting to a remote server takes around a second or two.

You can't control the speed in which a TCP connection is established, as that is handled entirely at the OS layer. The best you could do at the application layer is delay when that connection is attempted, such as by calling Sleep() inside of the OnStatus event during the hsResolving (DNS) and hsConnecting (TCP) states.
(12-01-2020, 05:52 PM)rlebeau Wrote: [ -> ]
(12-01-2020, 05:08 PM)Ahmed Sayed Wrote: [ -> ]Sorry. What I meant is that the client still connects to host faster than the simulated speed as it is still on the same machine, while connecting to a remote server takes around a second or two.

You can't control the speed in which a TCP connection is established, as that is handled entirely at the OS layer.  The best you could do at the application layer is delay when that connection is attempted, such as by calling Sleep() inside of the OnStatus event during the hsResolving (DNS) and hsConnecting (TCP) states.

Thanks for the reply, Is there like an equation or formula that to calculate how many milliseconds to sleep on those TCP states to mimic a speed of my selection?
(12-02-2020, 12:32 AM)Ahmed Sayed Wrote: [ -> ]Is there like an equation or formula that to calculate how many milliseconds to sleep on those TCP states to mimic a speed of my selection?

Did you look at the equations that TIdInterceptThrottler itself uses internally?

Code:
procedure TIdInterceptThrottler.Receive(var ABuffer: TIdBytes);
var
  LInterval: Int64;
begin
  inherited Receive(ABuffer);
  if RecvBitsPerSec > 0 then begin
    LInterval := (Int64(Length(ABuffer)) * 8 * 1000) div RecvBitsPerSec;
    while LInterval > MaxInt do begin
      TIdAntiFreezeBase.Sleep(MaxInt);
      Dec(LInterval, MaxInt);
    end;
    TIdAntiFreezeBase.Sleep(Integer(LInterval));
  end;
end;

procedure TIdInterceptThrottler.Send(var ABuffer: TIdBytes);
var
  LInterval: Int64;
begin
  inherited Send(ABuffer);
  if SendBitsPerSec > 0 then begin
    LInterval := (Int64(Length(ABuffer)) * 8 * 1000) div SendBitsPerSec;
    while LInterval > MaxInt do begin
      TIdAntiFreezeBase.Sleep(MaxInt);
      Dec(LInterval, MaxInt);
    end;
    TIdAntiFreezeBase.Sleep(Integer(LInterval));
  end;
end;

Though, a TCP connection is really not measured in bits/bytes-per-second after AFTER the connection is established. So, just use whatever sleep interval you want for the resolve/connect delay. For instance, if you want TIdTCPClient.Connect() to take 5+ seconds to complete, then just sleep for 5+ seconds.
(12-02-2020, 01:15 AM)rlebeau Wrote: [ -> ]
(12-02-2020, 12:32 AM)Ahmed Sayed Wrote: [ -> ]Is there like an equation or formula that to calculate how many milliseconds to sleep on those TCP states to mimic a speed of my selection?

Did you look at the equations that TIdInterceptThrottler itself uses internally?

Code:
procedure TIdInterceptThrottler.Receive(var ABuffer: TIdBytes);
var
  LInterval: Int64;
begin
  inherited Receive(ABuffer);
  if RecvBitsPerSec > 0 then begin
    LInterval := (Int64(Length(ABuffer)) * 8 * 1000) div RecvBitsPerSec;
    while LInterval > MaxInt do begin
      TIdAntiFreezeBase.Sleep(MaxInt);
      Dec(LInterval, MaxInt);
    end;
    TIdAntiFreezeBase.Sleep(Integer(LInterval));
  end;
end;

procedure TIdInterceptThrottler.Send(var ABuffer: TIdBytes);
var
  LInterval: Int64;
begin
  inherited Send(ABuffer);
  if SendBitsPerSec > 0 then begin
    LInterval := (Int64(Length(ABuffer)) * 8 * 1000) div SendBitsPerSec;
    while LInterval > MaxInt do begin
      TIdAntiFreezeBase.Sleep(MaxInt);
      Dec(LInterval, MaxInt);
    end;
    TIdAntiFreezeBase.Sleep(Integer(LInterval));
  end;
end;

Though, a TCP connection is really not measured in bits/bytes-per-second after AFTER the connection is established.  So, just use whatever sleep interval you want for the resolve/connect delay.  For instance, if you want TIdTCPClient.Connect() to take 5+ seconds to complete, then just sleep for 5+ seconds.

Thanks, for the example.
But what I meant is that, I have an internet speed of 30MB my transfer speed when I download anything is between 2.5 and 3.5 MB. I know Egypt still does not have fast internet connections, so, let's say that I want to mimic a speed of 512 kbps instead of 3.5 MB I believe if I used your example I should get an exact result on how much should I delay the request on the resolve DNS state or connect. Will that work and simulate the speed that I want?
(12-02-2020, 04:10 PM)Ahmed Sayed Wrote: [ -> ]But what I meant is that, I have an internet speed of 30MB my transfer speed when I download anything is between 2.5 and 3.5 MB. I know Egypt still does not have fast internet connections, so, let's say that I want to mimic a speed of 512 kbps instead of 3.5 MB I believe if I used your example I should get an exact result on how much should I delay the request on the resolve DNS state or connect. Will that work and simulate the speed that I want?

If you want to be technical about it - DNS requests and TCP handshakes exchange multiple IP packets back and forth. Those packets take up X bytes to transmit. So, if you want to simulate a 512kbps connection during the DNS resolve and TCP connect stages, then convert X to bits, multiply by 1000, and divide by 512kb, and that will be how many milliseconds minimum you need to sleep. It is just basic math.
Is there some event or property on indy clients that can provide with the size bytes X that needs to be transferred during the DNS resolve or TCP connect?


If it is not too much trouble can you provide me with a sample code to understand it better
(12-02-2020, 09:45 PM)Ahmed Sayed Wrote: [ -> ]Is there some event or property on indy clients that can provide with the size bytes X that needs to be transferred during the DNS resolve or TCP connect?

No. You would have to refer to the underlying DNS and TCP protocol specs to determine that.

For instance, during the connect stage, 3 TCP packets are exchanged (SYN, SYN+ACK, ACK). Each packet is 20-60 bytes for the IPv4 header (40+ bytes for an IPv6 header), plus 20-60 bytes for the TCP header. The actual sizes will vary depending on the particular TCP/IP options that are being used by the OS's socket stack and the application.

During the resolve stage, DNS also involves variable-length packets, which can be carried over UDP or TCP. So, you have the IPv4/IPv6 header, plus 8 bytes for the UDP header or 20-60 bytes for the TCP header, plus the actual DNS request/response data. And it may take multiple queries to adequately resolve a hostname to a viable IP address. I won't go into those details.

Use a packet sniffer, like Wireshark, to see these packets in action. You will then see exactly how large they really are, on your machine anyway. You can then approximate the sizes in your calculations.
Pages: 1 2