15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


Маааленькое PING-приложеньице :)

Протокол Ping предназначен для тестирования компьютерных соединений в Интернете путём посылки через протокол Internet Protocol (IP) по обределённому адресу сообщения и ожидания от него ответа.

ICMP - Internet Control Message Protocol. ICMP служит для передачи сообщений об ошибках а так же управляющих сообщений .   ICMP-тест может показать насколько быстро проходит информация между двумя узлами в Интернете.


1. Запускаем Delphi;
2. В Новом проекте добавляем в форму Tbutton, Tedit и Tmemo;
3. Вставляем “winsock”;
4. объявляем структурку для IP-заголовка:
type
  IPINFO = record
  Ttl     :char;
  Tos     :char;
  IPFlags :char;
  OptSize :char;
  Options :^char;
end;


5. объявляем структурку для хранения ICMP пакета:
type
  ICMPECHO = record
  Source  :longint;
  Status  :longint;
  RTTime  :longint;
  DataSize:Shortint;
  Reserved:Shortint;
  pData   :^variant;
  i_ipinfo:IPINFO;
end;


6. Объявляем функции и процедуры, которые мы будем вызывать из ICMP.DLL
TIcmpCreateFile = function():integer; {$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpCloseHandle = procedure(var handle:integer);{$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpSendEcho = function(var handle:integer; endereco:DWORD; buffer:variant; tam:WORD; IP:IPINFO; ICMP:ICMPECHO; tamicmp:DWORD; tempo:DWORD):DWORD;{$IFDEF WIN32} stdcall; {$ENDIF}


7. В Tbutton в событие Onclick вставляем следующий код:

procedure TForm1.Button1Click(Sender: TObject);
var
wsadt : wsadata;
icmp  :icmpecho;
HNDicmp : integer;
hndFile :integer;
Host :PHostEnt;
Destino :in_addr;
Endereco :^DWORD;
IP : ipinfo;
Retorno :integer;
dwRetorno :DWORD;
x :integer;

IcmpCreateFile : TIcmpCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;

begin
    if (edit1.Text = '') then begin
     Application.MessageBox('Enter a HostName ro a IP Adress',
                           'Error', MB_OK);
     exit;
    end;
    HNDicmp := LoadLibrary('ICMP.DLL');
    if (HNDicmp <> 0) then begin
       @IcmpCreateFile := GetProcAddress(HNDicmp,'IcmpCreateFile');
       @IcmpCloseHandle := GetProcAddress(HNDicmp,'IcmpCloseHandle');
       @IcmpSendEcho := GetProcAddress(HNDicmp,'IcmpSendEcho');
       if (@IcmpCreateFile=nil) or (@IcmpCloseHandle=nil) or (@IcmpSendEcho=nil) then  begin
         Application.MessageBox('Error getting ICMP Adress’,'Error', MB_OK);
         FreeLibrary(HNDicmp);
       end;
    end;
    Retorno := WSAStartup($0101,wsadt);

    if (Retorno <> 0) then begin
      Application.MessageBox('Canґt Load WinSockets','WSAStartup', MB_OK);
      WSACleanup();
      FreeLibrary(HNDicmp);
    end;

    Destino.S_addr := inet_addr(Pchar(Edit1.text));
    if (Destino.S_addr = 0) then begin
       Host := GetHostbyName(PChar(Edit1.text));
       end
    else begin
       Host := GetHostbyAddr(@Destino,sizeof(in_addr), AF_INET);
    end;

    if (host = nil) then begin
         Application.MessageBox('Host not found','Error', MB_OK);
         WSACleanup();
         FreeLibrary(HNDicmp);
         exit;
    end;
    memo1.Lines.Add('Pinging ' + Edit1.text);

    Endereco := @Host.h_addr_list;

    HNDFile := IcmpCreateFile();
    for x:= 0 to 4 do begin
      Ip.Ttl := char(255);
      Ip.Tos := char(0);
      Ip.IPFlags := char(0);
      Ip.OptSize := char(0);
      Ip.Options := nil;

      dwRetorno := IcmpSendEcho(
                   HNDFile,
                   Endereco^,
                   null,
                   0,
                   Ip,
                   Icmp,
                   sizeof(Icmp),
                   DWORD(5000));
      Destino.S_addr := icmp.source;
      Memo1.Lines.Add('Ping ' + Edit1.text);
     end;


   IcmpCLoseHandle(HNDFile);
   FreeLibrary(HNDicmp);
   WSACleanup();
end;


У данного примера есть один недостаток - программа не воспримет доменное имя, только IP-адресс. Для пользователей NT не используйте функцию IcmpCloseHandle.

Это всё…..

Ну и в конце полный исходный код примера:

----------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  winsock, StdCtrls;

type
  IPINFO = record
  Ttl     :char;
  Tos     :char;
  IPFlags :char;
  OptSize :char;
  Options :^char;
end;

type
ICMPECHO = record
Source  :longint;
Status  :longint;
RTTime  :longint;
DataSize:Shortint;
Reserved:Shortint;
pData   :^variant;
i_ipinfo:IPINFO;
end;

TIcmpCreateFile = function():integer; {$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpCloseHandle = procedure(var handle:integer);{$IFDEF WIN32} stdcall; {$ENDIF}
TIcmpSendEcho = function(var handle:integer; endereco:DWORD; buffer:variant; tam:WORD; IP:IPINFO; ICMP:ICMPECHO; tamicmp:DWORD; tempo:DWORD):DWORD;{$IFDEF WIN32} stdcall; {$ENDIF}


type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.Button1Click(Sender: TObject);
var
wsadt : wsadata;
icmp  :icmpecho;
HNDicmp : integer;
hndFile :integer;
Host :PHostEnt;
Destino :in_addr;
Endereco :^DWORD;
IP : ipinfo;
Retorno :integer;
dwRetorno :DWORD;
x :integer;

IcmpCreateFile : TIcmpCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;

begin
    if (edit1.Text = '') then begin
     Application.MessageBox('Digite um HostName ou um End. IP',
                           'Error', MB_OK);
     exit;
    end;
    HNDicmp := LoadLibrary('ICMP.DLL');
    if (HNDicmp <> 0) then begin
       @IcmpCreateFile := GetProcAddress(HNDicmp,'IcmpCreateFile');
       @IcmpCloseHandle := GetProcAddress(HNDicmp,'IcmpCloseHandle');
       @IcmpSendEcho := GetProcAddress(HNDicmp,'IcmpSendEcho');
       if (@IcmpCreateFile=nil) or (@IcmpCloseHandle=nil) or (@IcmpSendEcho=nil) then  begin
         Application.MessageBox('Erro pegando endereзos ICMP','Error', MB_OK);
         FreeLibrary(HNDicmp);
       end;
    end;
    Retorno := WSAStartup($0101,wsadt);

    if (Retorno <> 0) then begin
      Application.MessageBox('Nгo foi possнvel carregar WinSockets','WSAStartup', MB_OK);
      WSACleanup();
      FreeLibrary(HNDicmp);
    end;

    Destino.S_addr := inet_addr(Pchar(Edit1.text));
    if (Destino.S_addr = 0) then begin
       Host := GetHostbyName(PChar(Edit1.text));
       end
    else begin
       Host := GetHostbyAddr(@Destino,sizeof(in_addr), AF_INET);
    end;

    if (host = nil) then begin
         Application.MessageBox('Host nгo encontrado','Error', MB_OK);
         WSACleanup();
         FreeLibrary(HNDicmp);
         exit;
    end;
    memo1.Lines.Add('Pinging ' + Edit1.text);

    Endereco := @Host.h_addr_list;

    HNDFile := IcmpCreateFile();
    for x:= 0 to 4 do begin
      Ip.Ttl := char(255);
      Ip.Tos := char(0);
      Ip.IPFlags := char(0);
      Ip.OptSize := char(0);
      Ip.Options := nil;

      dwRetorno := IcmpSendEcho(
                   HNDFile,
                   Endereco^,
                   null,
                   0,
                   Ip,
                   Icmp,
                   sizeof(Icmp),
                   DWORD(5000));
      Destino.S_addr := icmp.source;
      Memo1.Lines.Add('Pingou ' + Edit1.text);
     end;


   IcmpCLoseHandle(HNDFile);
   FreeLibrary(HNDicmp);
   WSACleanup();
end;

end.
--------------------------------------------