Correct DL & UP on INDY 10'S TIDMAPPEDPORTTCP

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Correct DL & UP on INDY 10'S TIDMAPPEDPORTTCP

Postby Munfaqqiha » Sun Jul 05, 2015 10:31 am

On Delphi XE8, the results of all the codes that I use running smoothly, but when I apply in C ++ Builder XE8, the results are not as desired.

Delphi XE8 codes (some of which are the work of Remy Lebeau) can be seen below :

Code: Select all
//------------------------------------------------------------ UNIT1.PASS ---
..............
type
  TForm1 = class(TForm)
..............
    Procedure ShapeUpload;
    Procedure ShapeDownload;
..............

var
  Form1     : TForm1;
  Upload    : Int64;
  Download  : Int64;
  TotalUpload   : Int64;
  TotalDownload : Int64;
  ForDLSpeed    : Integer;
  ForULSpeed    : Integer;

implementation

..............

{$R *.dfm}

function BytesConvert(Value : DWord) : string;
 const
   OneKB = 1024;
   OneMB = OneKB * 1024;
   OneGB = OneMB * 1024;
begin

if Value < OneKB then
  Result := FormatFloat(' B/s',Value)
else if Value < OneMB then
  Result := FormatFloat(' Kb/s', Value / OneKB)
else if Value < OneGB then
  Result := FormatFloat(' Mb/s', Value / OneMB)
end;

function FormatBytes(ABytes: Int64): string;
begin
  if ABytes < 1024 then
    Result := FormatFloat('#,0 Bytes', ABytes)
  else if ABytes < 1048576 then
    Result := FormatFloat('#,##0.00 Kb', ABytes / 1024)
  else if ABytes < 1073741824 then
    Result := FormatFloat('#,##0.00 Mb', ABytes / 1048576)
  else if ABytes < 1099511627776 then
    Result := FormatFloat('#,##0.00 Gb', ABytes / 1073741824)
  else
    Result := FormatFloat('#,##0.00 Tb', ABytes / 1099511627776);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  UploadSpeed.Caption   := FormatFloat('0',Upload/1024);
  DownloadSpeed.Caption := FormatFloat('0',Download/1024);

  Upload  := 0;
  Download:= 0;

  TTDL.Caption := 'T.DL: ' + FormatBytes(TotalDownload);
  TTUP.Caption := 'T.UP: ' + FormatBytes(TotalUpload);

  LabelDLSpeed.Caption:= BytesConvert(ForDLSpeed);
  LabelULSpeed.Caption:= BytesConvert(ForULSpeed);
  ForDLSpeed := 0;
  ForULSpeed := 0;
end;

procedure TForm1.ShapeUpload;
begin
   ShapeUL.Refresh;
if ShapeUL.brush.color  = clRed
then begin
  ShapeUL.brush.color  := clWhite;
end else begin
   ShapeUL.brush.color := clRed;
  end;
end;

procedure TForm1.ShapeDownload;
begin
   ShapeDL.Refresh;
if ShapeDL.brush.color  =  clLime
then begin
   ShapeDL.brush.color :=  $00009300;
end else
begin
   ShapeDL.brush.color := clLime;
  end;
end;

procedure TForm1.IdMappedPortTCP1Execute(AContext: TIdContext);
begin
  ..............
  ShapeUpload;
  ForULSpeed  := ForULSpeed   + Length(netstring(AContext));
  TotalUpload := TotalUpload + Length(netstring(AContext));
  Upload      := Upload    + Length(netstring(AContext));
end;

procedure TForm1.IdMappedPortTCP1OutboundData(AContext: TIdContext);
begin
  ..............
  ShapeDownload;
  ForDLSpeed    := ForDLSpeed   + Length(netstring(AContext));
  TotalDownload := TotalDownload + Length(netstring(AContext));
  Download      := Download + Length(netstring(AContext));
end;

Meanwhile, the converted code to C ++ Builder XE8, you can see here:

Code: Select all
//--------------------------------------------------------------- UNIT1.H ---
class TForm1 : public TForm
{
__published:   // IDE-managed Components
        ..............
   void __fastcall ShapeUpload(void);
   void __fastcall ShapeDownload(void);
        ..............
#endif

//------------------------------------------------------------- UNIT1.CPP ---
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#pragma package(smart_init)
..............
#pragma resource "*.dfm"
TForm1 *Form1;
//------------------------------------------------------------- VARIABLES ---
  __int64 Upload;
  __int64 Download;
  __int64 TotalUpload;
  __int64 TotalDownload;
  int ForDLSpeed;
  int ForULSpeed;
  ..............
//------------------------------------------------- BYTESCONVERT FUNCTION ---
String __fastcall BytesConvert(DWord Value)
{
  const int OneKB = 1024;
  const int OneMB = OneKB * 1024;
  const int OneGB = OneMB * 1024;

 if (Value < OneKB)
  { return FormatFloat(" B/s", Value); }
 else if (Value < OneMB)
  { return FormatFloat(" Kb/s", Value / OneKB); }
 else if (Value < OneGB)
  { return FormatFloat(" Mb/s", Value / OneMB); }
}
//-------------------------------------------------- FORMATBYTES FUNCTION ---
String __fastcall FormatBytes(__int64 ABytes)
{
  if (ABytes < 1024)
  { return FormatFloat("#,0 Bytes", ABytes); }
  else if (ABytes < 1048576)
  { return FormatFloat("#,##0.00 Kb", ABytes / 1024); }
  else if (ABytes < 1073741824)
  { return FormatFloat("#,##0.00 Mb", ABytes / 1048576); }
  else if (ABytes < 1099511627776)
  { return FormatFloat("#,##0.00 Gb", ABytes / 1073741824); }
  else
  return FormatFloat("#,##0.00 Tb", ABytes / 1099511627776);
}
//----------------------------------------------------------------- TIMER ---
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
  UploadSpeed->Caption   = FormatFloat("0",Upload/1024);
  DownloadSpeed->Caption = FormatFloat("0",Download/1024);

  Upload   = 0;
  Download = 0;

  TTDL->Caption = "T.DL: " + FormatBytes(TotalDownload);
  TTUP->Caption = "T.UP: " + FormatBytes(TotalUpload);

  LabelDLSpeed->Caption = BytesConvert(ForDLSpeed);
  LabelULSpeed->Caption = BytesConvert(ForULSpeed);

  ForDLSpeed = 0;
  ForULSpeed = 0;
}
//----------------------------------------------------------- SHAPEUPLOAD ---
void __fastcall TForm1::ShapeUpload(void)
 {
   ShapeUL = new TShape(this);
   ShapeUL->Refresh();
   if (ShapeUL->Brush->Color == clRed)
   { ShapeUL->Brush->Color = clWhite; }
   else
   { ShapeUL->Brush->Color = clRed; }
 }

//--------------------------------------------------------- SHAPEDOWNLOAD ---
void __fastcall TForm1::ShapeDownload(void)
 {
   ShapeDL = new TShape(this);
   ShapeDL->Refresh();
   if (ShapeDL->Brush->Color == clLime)
   { ShapeDL->Brush->Color = clFuchsia; }
   else
   { ShapeDL->Brush->Color = clLime; }
 }
//------------------------------------------ TIDMAPPEDPORTTCP (OnExecute) ---
void __fastcall TForm1::IdMappedPortTCP1Execute(TIdContext *AContext)
{
  TIdMappedPortContext *Internet = (TIdMappedPortContext*)AContext;
  // ShapeUpload(void);
  ShapeUL;
  String ForULSpeed  = ForULSpeed + netstring(Internet);
  String TotalUpload = TotalUpload + netstring(Internet);
  String Upload      = Upload + netstring(Internet);
  ..............
}

//------------------------------------- TIDMAPPEDPORTTCP (OnOutboundData) ---
void __fastcall TForm1::IdMappedPortTCP1OutboundData(TIdContext *AContext)
{
  TIdMappedPortContext *Internet = (TIdMappedPortContext*)AContext;
  // ShapeDownload();
  ShapeDL;
  String ForDLSpeed    = ForDLSpeed + netstring(Internet);
  String TotalDownload = TotalDownload + netstring(Internet);
  String Download      = Download + netstring(Internet);
  ..............
}

The problem that arises is:
  1. The traffic shape is not working.
  2. The download speed and upload is not working, too.
  3. The Total download and upload also is not working.
So, what is the correct way to write the working code ?

Thank you so much.

Cheers,
M
Last edited by Munfaqqiha on Mon Jul 06, 2015 12:56 pm, edited 1 time in total.
User avatar
Munfaqqiha
 
Posts: 4
Joined: Sun Jul 05, 2015 10:04 am
Location: Lombok, Indonesia

Re: Correct DL & UP on INDY 10'S TIDMAPPEDPORTTCP

Postby rlebeau » Sun Jul 05, 2015 8:32 pm

Munfaqqiha wrote:On Delphi XE8, the results of all the codes that I use running smoothly, but when I apply in C ++ Builder XE8, the results are not as desired.


The C++ code is not doing the same thing that the Delphi code is doing. Most notably:

1. it is not initializing the global variables.
2. the OnExecute/OnOutboundData event handlers are not reading the Length of the netstring values, and are assigning values to local string variables instead of the global integer values.
3. ShapeUpload()/ShapeDownload() are creating new TShape objects every time they are called.

Also, in both Delphi and C++:

1. The result of BytesConvert() is undefined for values >= 1GB, and the FormatFloat() calls are not actually formatting the numeric values being passed to them. For that matter, BytesConvert() is redundant and should be removed, as it is not doing anything that FormatBytes() is not doing.
2. you should not be calling netstring() at all in this situation, as it is unnecessary overhead, and may skew the calculations. You should be counting the raw bytes, not string characters.
3. TIdMappedPortTCP is a multithreaded component, but ShapeUpload()/ShapeDownload() are accessing UI controls in a thread unsafe manner.

Try this instead:

Code: Select all
class TForm1 : public TForm
{
__published:   // IDE-managed Components
        ..............
   void __fastcall ShapeUpload(void)
   void __fastcall ShapeDownload(void)
        ..............
};


Code: Select all
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#pragma package(smart_init)
..............
#pragma resource "*.dfm"
TForm1 *Form1;
//------------------------------------------------------------- VARIABLES ---
  __int64 Upload = 0;
  __int64 Download = 0;
  __int64 TotalUpload = 0;
  __int64 TotalDownload = 0;
  int ForDLSpeed = 0;
  int ForULSpeed = 0;
  ..............
  static const __int64 OneKB = 1024;
  static const __int64 OneMB = OneKB * 1024;
  static const __int64 OneGB = OneMB * 1024;
  static const __int64 OneTB = OneGB * 1024;
//-------------------------------------------------- FORMATBYTES FUNCTION ---
String __fastcall FormatBytes(__int64 ABytes)
{
  if (ABytes < OneKB)
  { return FormatFloat("#,0 Bytes", ABytes); }
  else if (ABytes < OneMB)
  { return FormatFloat("#,##0.00 Kb", ABytes / OneKB); }
  else if (ABytes < OneGB)
  { return FormatFloat("#,##0.00 Mb", ABytes / OneMB); }
  else if (ABytes < OneTB)
  { return FormatFloat("#,##0.00 Gb", ABytes / OneGB); }
  else
  return FormatFloat("#,##0.00 Tb", ABytes / OneTB);
}
//----------------------------------------------------------------- TIMER ---
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
  UploadSpeed->Caption   = FormatFloat("0",Upload/OneKB);
  DownloadSpeed->Caption = FormatFloat("0",Download/OneKB);

  Upload   = 0;
  Download = 0;

  TTDL->Caption = "T.DL: " + FormatBytes(TotalDownload);
  TTUP->Caption = "T.UP: " + FormatBytes(TotalUpload);

  LabelDLSpeed->Caption = FormatBytes(ForDLSpeed)+"/s";
  LabelULSpeed->Caption = FormatBytes(ForULSpeed)+"/s"

  ForDLSpeed = 0;
  ForULSpeed = 0;
}
//----------------------------------------------------------- SHAPEUPLOAD ---
void __fastcall TForm1::ShapeUpload(void)
 {
   ShapeUL->Refresh();
   if (ShapeUL->Brush->Color == clRed)
   { ShapeUL->Brush->Color = clWhite; }
   else
   { ShapeUL->Brush->Color = clRed; }
 }
//--------------------------------------------------------- SHAPEDOWNLOAD ---
void __fastcall TForm1::ShapeDownload(void)
 {
   ShapeDL->Refresh();
   if (ShapeDL->Brush->Color == clLime)
   { ShapeDL->Brush->Color = clFuchsia; }
   else
   { ShapeDL->Brush->Color = clLime; }
 }
//------------------------------------------ TIDMAPPEDPORTTCP (OnExecute) ---
void __fastcall TForm1::IdMappedPortTCP1Execute(TIdContext *AContext)
{
  TIdMappedPortContext *Internet = (TIdMappedPortContext*)AContext;
  TThread::Queue(NULL, &ShapeUpload);
  ForULSpeed  += Internet->NetData.Length;
  TotalUpload += Internet->NetData.Length;
  Upload      += Internet->NetData.Length;
  ..............
}
//------------------------------------- TIDMAPPEDPORTTCP (OnOutboundData) ---
void __fastcall TForm1::IdMappedPortTCP1OutboundData(TIdContext *AContext)
{
  TIdMappedPortContext *Internet = (TIdMappedPortContext*)AContext;
  TThread::Queue(NULL, &ShapeDownload);
  ForDLSpeed    += Internet->NetData.Length;
  TotalDownload += Internet->NetData.Length;
  Download      += Internet->NetData.Length;
  ..............
}
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1603
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Correct DL & UP on INDY 10'S TIDMAPPEDPORTTCP

Postby Munfaqqiha » Sat Jul 11, 2015 2:44 am

Remy Lebeau, there's a forgotten thing you should to know.

The results of FormatBytes code above works perfectly in Delphi. All digits are keep moving change according to the speed or the total download/upload. See the result screenshots here.

I'm sorry, however, in C ++ Builder XE8, which moves changed, just the first digit only, while the last two zeros are remain unchanged. The result screenshots is here. This happened both when using the format:

Code: Select all
return FormatFloat("#,##0.00 Kb", ABytes / OneKB) so on...

and also

Code: Select all
return FormatFloat("#,##0.00 Kb", ABytes / 1024) so on...

I have tried some of freeform text and control characters format options, but only by using the Double floating point type that can resolve it.

So the working codes are:

Code: Select all
String __fastcall FormatBytes(__int64 ABytes)
{
 if (ABytes < KiB)
   return FormatFloat("#,0 Bytes", ABytes);
  else
   if (ABytes < MiB)
     return FormatFloat("#,##0.00 KiB", double(ABytes) / KiB);
   else
     if (ABytes < GiB)
      return FormatFloat("#,##0.00 MiB", double(ABytes) / MiB);
     else
      if (ABytes < TiB)
        return FormatFloat("#,##0.00 GiB", double(ABytes) / GiB);
      else
         return FormatFloat("#,##0.00 TiB", double(ABytes) / TiB);
}


Thank you so much..

Greetz,
M
User avatar
Munfaqqiha
 
Posts: 4
Joined: Sun Jul 05, 2015 10:04 am
Location: Lombok, Indonesia

Re: Correct DL & UP on INDY 10'S TIDMAPPEDPORTTCP

Postby rlebeau » Mon Jul 13, 2015 11:58 am

Munfaqqiha wrote:only by using the Double floating point type that can resolve it.


My bad. The Delphi code is using the '/' floating-point division operation, instead of the 'div' integer division operator. The C++ code I provided for FormatBytes() was using integer division instead of floating-point division, thus there would never be anything but zeros after the decimal point. So yes, an explicit type-cast to 'double' is needed to provide valid digits after the decimal.
Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1603
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA


Return to Technical

Who is online

Users browsing this forum: Bing [Bot], Majestic-12 [Bot] and 16 guests