Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » Delphi - Работа с сетью »

Обсудить на форуме Обсудить на форуме

Пингуем (Ping) под Delphi

Протокол 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. 

Может пригодится:


Автор: Неизвестен
Прочитано: 13336
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (3)

Прислал: demonvex
Помоему этот код только делает вид что пингует. У меня всегда выдается ошибка 122 "The data area passed to a system call is too small."

Прислал: Саша
э... ну, пропинговался адрес, пришёл ответ, что соединение состоялось, а где параметры пинга? время отклика, ttl?

Прислал: Заебали копипастить
Пиздец! ленивые админы! Одна и та же инфа на всех сайтах! вы хоть проверили этот код перед тем как публиковать? пизда!!! заебали ленивые админы!!!!!

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру