Sources
Delphi Russian Knowledge Base
DRKB - это самая большая и удобная в использовании база знаний по Дельфи в рунете, составленная Виталием Невзоровым

Формулы передачи данных для начинающих

01.01.2007

Автор: Jason Pierce

Данным примером я попытаюсь дать ответы на следующие вопросы:

Каково различие между KBps и Kbps? В чём заключается отличие битов, байтов и бодов? Как определить скорость передачи данных? Как выяснить, насколько долго будет загружаться файл с определённой скоростью? Как посчитать время, оставшее до окончания загрузки?

Для начала хотельсы навести порядок с некоторой неразберихой по поводу KBps и Kbps (буква b в нижнем регистре). KBps это обозначение для килобайт в секунду, в то время как Kbps обозначает килобиты в секунду. 1 килобайт (KB) = 8 килобитам (Kb).

Когда речь идёт о скорости передачи, то применяется Kbps. Таким образом модем со скорость передачи 33.6K (33600 bps) передаёт данные со скоростью 4.2 KBps (4.2 килобайта в секунду). Как мы видим, разница между KB и Kb довольно ощутима. В этом кроется причина того, что некоторые пользователи модемов по своему незнанию не могут понять, почему данные передаются так медленно. На самом деле данные объёмом 33.6K передаются не за 1 секунду, а за 8, соответственно за одну секунду будет передано 33.6 Kb / 8 = 4.2.

Так же хотелось бы дать некоторые разъяснения по поводу слова "бод" (baud). Обычно для модема "боды" расшифровываются как бит в секунду. На самом деле это не так. Бод (Baud) означает частоту звука в телефонной линии. Т. е. в зависимости от модема, который Вы используете, количество бит, которые могут быть переданы зависит от частоты звука, необходимой для обеспечения нужной скорости передачи.

Обратите внимание: Приведённый ниже пример, использует компонент NetMasters TNMHTTP. Однако, если Вы "прикипели" к какому-то другому компоненту TCP/IP, то переделать пример под этот компонент не составит большого труда.

Используемые обозначения:

bps = байт, переданных за 1 секунду

KBps (KB/Sec) = bps / 1024

Kbps (Kb/Sec) = KBps x 8

Краткий алгоритм приведённого ниже примера:

1. Сохраняем в переменной время начала загрузки: nStartTime := GetTickCount;

2. Сохраняем в переменной размер файла (KB): nFileSize := "File Size";

3. Начало передачи данных.

4. Обновляем количество переданных байт: Inc(nBytesTransferred, nNewBytes);

5. Получаем оставшееся время: nTimeElapsed := (GetTickCount - nStartTime) / 1000;

6. Вычисляем bps: nBps := BytesTransferred / nTimeElapsed;

7. Вычисляем KBps: nKBps := nBps / 1024;

Используемые данные:

Общее время скачивания (секунд) := nFileSize / nKBps;

bps := FloatToStr(nBps);

KB/Sec (KBps) := FloatToStr(nKBps);

Осталось секунд := FloatToStr(((nFileSize - BytesTransferred) / 1024) / KBps);

Рабочий пример:

unit Main; 
 
interface
 
uses
 
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 
StdCtrls, Gauges, Psock, NMHttp;
 
type
 
TfMain = class(TForm)
    Label1
: TLabel;
    eURL
: TEdit;
    bGet
: TButton;
    lbMessages
: TListBox;
    gbDetails
: TGroupBox;
    lEstimate
: TLabel;
    lKBps
: TLabel;
    lReceived
: TLabel;
    lRemaining
: TLabel;
    gProgress
: TGauge;
    NMHTTP1
: TNMHTTP;
    lbps
: TLabel;
    bCancel
: TButton;
    procedure NMHTTP1PacketRecvd
(Sender: TObject);
    procedure bGetClick
(Sender: TObject);
    procedure bCancelClick
(Sender: TObject);
    procedure NMHTTP1Connect
(Sender: TObject);
    procedure NMHTTP1ConnectionFailed
(Sender: TObject);
    procedure NMHTTP1Disconnect
(Sender: TObject);
    procedure NMHTTP1Failure
(Cmd: CmdType);
    procedure NMHTTP1HostResolved
(Sender: TComponent);
    procedure NMHTTP1InvalidHost
(var Handled: Boolean);
    procedure NMHTTP1Status
(Sender: TComponent; Status: String);
    procedure NMHTTP1Success
(Cmd: CmdType);
 
private
   
{ Private declarations }
   
function ss2nn(Seconds: Integer): String;
 
public
   
{ Public declarations }
 
end;
 
var
  fMain
: TfMain;
  nFileSize
: Double;
  nStartTime
: DWord;
 
implementation
 
{$R *.DFM}
 
{Цель этой функции состоит в том, чтобы определить, сколько минут и секунд там находятся в данном количестве секунд}
function TfMain.ss2nn(Seconds: Integer): String;
var
  nMin
, nSec: Integer;
begin
 
{Проверяем, меньше чем 1/Min}
 
if Seconds < 60 then Result := '0 minutes ' + IntToStr(Seconds) + ' seconds'
 
else begin
   
{Определяем минуты}
    nMin
:= Seconds div 60;
   
{Определяем секунды}
    nSec
:= Seconds - (nMin * 60);
   
{Возвращаем результат}
   
Result := IntToStr(nMin) + ' minutes ' + IntToStr(nSec) + ' seconds';
 
end;
end;
 
procedure
TfMain.NMHTTP1PacketRecvd(Sender: TObject);
var
  nBytesReceived
, nTimeElapsed, nBps, nKBps: Double;
begin
 
{Следующий код выполняется только однажды, при приёме первого пакета}
 
if nFileSize <> NMHTTP1.BytesTotal then
 
begin
   
{Получаем размер файла}
    nFileSize
:= NMHTTP1.BytesTotal;
   
{Вычисляем время передачи, исходя из скорости соединения 33.6 Kbps}
    lEstimate
.Caption := 'Estimated download time at 33.6 Kbps: ' + ss2nn(Round(
     
(nFileSize / 1024) / 4.2));
   
{Получаем время начала}
    nStartTime
:= GetTickCount;
 
end;
 
 
{Обновляем nBytesReceived}
  nBytesReceived
:= NMHTTP1.BytesRecvd;
 
 
{Вычисляем количество секунд прошедших с момента начала передачи}
  nTimeElapsed
:= (GetTickCount - nStartTime) / 1000;
 
{Проверяем на 0/Sec, если так, то устанавливаем 1, чтобы предотвратить деления на ноль}
 
if nTimeElapsed = 0 then nTimeElapsed := 1;
 
 
{Вычисляем байт в секунду}
  nBps
:= nBytesReceived / nTimeElapsed;
 
{Вычисляем килобайт в секунду}
  nKBps
:= nBps / 1024;
 
 
{Обновляем контролы}
  gProgress
.Progress := Round((nBytesReceived * 100) / nFileSize);
  lbps
.Caption := IntToStr(Round(nBps * 8)) + ' bits per second';
  lKBps
.Caption := IntToStr(Round(nKBps)) + ' KB/Sec (KBps)';
  lReceived
.Caption := FloatToStr(nBytesReceived) + ' of ' + FloatToStr(
    nFileSize
) + ' bytes received';
  lRemaining
.Caption := ss2nn(Round(((nFileSize - nBytesReceived) / 1024) /
    nKBps
)) + ' remaining';
end;
 
procedure
TfMain.bGetClick(Sender: TObject);
begin
 
{Сбрасываем переменные}
  nFileSize
:= 0;
 
 
{Обнуляем контролы}
  lbMessages
.Clear;
  gProgress
.Progress := 0;
  lEstimate
.Caption := 'Estimated download time at 33.6 Kbps: 0 minutes 0 ' +
   
'seconds';
  lbps
.Caption := '0 bits per second';
  lKBps
.Caption := '0 KB/Sec (KBps)';
  lReceived
.Caption := '0 of 0 bytes received';
  lRemaining
.Caption := '0 minutes 0 seconds remaining';
 
 
{Получаем файл}
  NMHTTP1
.Get(eURL.Text);
end;
 
procedure
TfMain.bCancelClick(Sender: TObject);
begin
 
{Разрываем соединение с сервером}
  NMHTTP1
.Disconnect;
 
 
{Обновляем lbMessages}
  lbMessages
.Items.Append('Get Canceled');
  lbMessages
.Items.Append('Disconnected');
end;
 
procedure
TfMain.NMHTTP1Connect(Sender: TObject);
begin
 
{Запрещаем/Разрешаем контролы}
  bGet
.Enabled := False;
  bCancel
.Enabled := True;
 
 
{Работаем с lbMessages}
 
with lbMessages.Items do
 
begin
   
Append('Connected');
   
Append('Local Address: ' + NMHTTP1.LocalIP);
   
Append('Remote Address: ' + NMHTTP1.RemoteIP);
 
end;
end;
 
procedure
TfMain.NMHTTP1ConnectionFailed(Sender: TObject);
begin
 
ShowMessage('Connection Failed.');
end;
 
procedure
TfMain.NMHTTP1Disconnect(Sender: TObject);
begin
 
{Запрещаем/Разрешаем контролы}
  bCancel
.Enabled := False;
  bGet
.Enabled := True;
 
 
{Обновляем lbMessages}
 
if NMHTTP1.Connected then lbMessages.Items.Append('Disconnected');
end;
 
procedure
TfMain.NMHTTP1Failure(Cmd: CmdType);
begin
 
case Cmd of
   
CmdGET    : lbMessages.Items.Append('Get Failed');
   
CmdOPTIONS: lbMessages.Items.Append('Options Failed');
   
CmdHEAD   : lbMessages.Items.Append('Head Failed');
   
CmdPOST   : lbMessages.Items.Append('Post Failed');
   
CmdPUT    : lbMessages.Items.Append('Put Failed');
   
CmdPATCH  : lbMessages.Items.Append('Patch Failed');
   
CmdCOPY   : lbMessages.Items.Append('Copy Failed');
   
CmdMOVE   : lbMessages.Items.Append('Move Failed');
   
CmdDELETE : lbMessages.Items.Append('Delete Failed');
   
CmdLINK   : lbMessages.Items.Append('Link Failed');
   
CmdUNLINK : lbMessages.Items.Append('UnLink Failed');
   
CmdTRACE  : lbMessages.Items.Append('Trace Failed');
   
CmdWRAPPED: lbMessages.Items.Append('Wrapped Failed');
 
end;
end;
 
procedure
TfMain.NMHTTP1HostResolved(Sender: TComponent);
begin
  lbMessages
.Items.Append('Host Resolved');
end;
 
procedure
TfMain.NMHTTP1InvalidHost(var Handled: Boolean);
begin
 
ShowMessage('Invalid Host. Please specify a new URL.');
end;
 
procedure
TfMain.NMHTTP1Status(Sender: TComponent; Status: String);
begin
 
if NMHTTP1.ReplyNumber = 404 then ShowMessage('Object Not Found.');
end;
 
procedure
TfMain.NMHTTP1Success(Cmd: CmdType);
begin
 
case Cmd of
   
{Удостоверяемся, что процедура получения не была прервана}
   
CmdGET: if NMHTTP1.Connected then lbMessages.Items.Append('Get Succeeded');
 
   
CmdOPTIONS: lbMessages.Items.Append('Options Succeeded');
   
CmdHEAD   : lbMessages.Items.Append('Head Succeeded');
   
CmdPOST   : lbMessages.Items.Append('Post Succeeded');
   
CmdPUT    : lbMessages.Items.Append('Put Succeeded');
   
CmdPATCH  : lbMessages.Items.Append('Patch Succeeded');
   
CmdCOPY   : lbMessages.Items.Append('Copy Succeeded');
   
CmdMOVE   : lbMessages.Items.Append('Move Succeeded');
   
CmdDELETE : lbMessages.Items.Append('Delete Succeeded');
   
CmdLINK   : lbMessages.Items.Append('Link Succeeded');
   
CmdUNLINK : lbMessages.Items.Append('UnLink Succeeded');
   
CmdTRACE  : lbMessages.Items.Append('Trace Succeeded');
   
CmdWRAPPED: lbMessages.Items.Append('Wrapped Succeeded');
 
end;
end;
 
end.

Взято из https://forum.sources.ru