自己用的一个Ping控件
unit fgNet;
interface
uses
Windows, SysUtils, Classes, Forms, WinSock, WinInet;
type
PIPOptionInfomation=^TIPOptionInfomation;
TIPOptionInfomation=packed record
TTL:byte; //Time to Live 发送数据成活期(最大跳转网关数目)
TOS:byte; //服务类型
Flags:byte;
OptionsSize:byte;
OptionsData
Char;
end;
PIcmpEchoReply=^TIcmpEchoReply;
TIcmpEchoReply=packed record
Address
WORD;
Status
WORD;
RTT
WORD;
DataSize:Word;
Reserved:Word;
Data
ointer;
Options:TIPOptionInfomation;
end;
TIcmpCreateFile=function:THandle; stdcall;
TIcmpCloseHandle=function(IcmpHandle:THandle):boolean; stdcall;
TIcmpSendEcho=function(IcmpHandle:THandle;
DestinationAddress
WORD;
RequestData
ointer;
RequestSize:Word;
RequestOptions
IPOptionInfomation;
ReplyBuffer
ointer;
ReplySize
WORD;
Timeout
WORD)
WORD; stdcall;
TfgOnPing=procedure(Succ:boolean;IP:string;Bytes:Word;Tims
WORD;TTL:Byte) of Object; //OnPing事件类
TfgOnPingStatus=procedure(Status:string) of Object; //Ping状态事件
{ Ping 控件 }
TfgPing=class(TComponent)
private
hIcmpDll:HMODULE;
f_CheckStr:string;
f_TTL:byte;
f_Status:string;
f_PingStatus:TfgOnPingStatus;
f_IP:string;
f_Host:string;
f_Timeout
WORD;
f_OnPing:TfgOnPing;
f_Pinging:boolean;
hICMP:THandle;
IcmpCreateFile:TIcmpCreateFile;
IcmpCloseHandle:TIcmpCloseHandle;
IcmpSendEcho:TIcmpSendEcho;
procedure SetStatus(Value:string);
protected
public
constructor Create(AOwner:TComponent); override;
destructor Destroy; override;
function Ping:boolean;
property Status:string read f_Status write SetStatus;
property Pinging:boolean read f_Pinging;
published
property Timeout
WORD read f_Timeout write f_Timeout; //超时时间
property IPAddr:string read f_IP; //目标IP地址
property Host:string read f_host write f_host;
property TTL:byte read f_TTL write f_TTL; //最大跳转网关数目
property CheckStr:string read f_CheckStr write f_CheckStr; //测试字符串
property OnPing:TfgOnPing read f_OnPing write f_OnPing; //Ping事件
property OnStatus:TfgOnPingStatus read f_PingStatus write f_PingStatus; //状态事件
end;
implementation
const
INVALID_IP_ADDRESS= $ffffffff;
function HostName2IP(const HostName:string):longint;
var
RemoteHost : PHostEnt; (* no, don't free it! *)
ip_address: longint;
(*$ifdef ver80 *)
s: string;
(*$else *)
(*$ifopt h- *)
s: string;
(*$endif *)
(*$endif *)
begin //主机名解析为IP地址
ip_address:=INVALID_IP_ADDRESS;
try
if hostname='' then begin (* no host given! *)
Result:=ip_address;
EXIT;
end
else begin
(*@/// ip_address:=Winsock.Inet_Addr(PChar(hostname)); { try a xxx.xxx.xxx.xx first } *)
(*$ifdef ver80 *)
s:=hostname+#0;
ip_address:=Winsock.Inet_Addr(PChar(@s[1])); (* try a xxx.xxx.xxx.xx first *)
(*$else *)
(*$ifopt h- *)
s:=hostname+#0;
ip_address:=Winsock.Inet_Addr(PChar(@s[1])); (* try a xxx.xxx.xxx.xx first *)
(*$else *)
ip_address:=Winsock.Inet_Addr(PChar(hostname)); (* try a xxx.xxx.xxx.xx first *)
(*$endif *)
(*$endif *)
(*@///*)
if ip_address=SOCKET_ERROR then begin
(*@/// RemoteHost:=Winsock.GetHostByName(PChar(hostname)); *)
(*$ifdef ver80 *)
RemoteHost:=Winsock.GetHostByName(PChar(@s[1]));
(*$else *)
(*$ifopt h- *)
RemoteHost:=Winsock.GetHostByName(PChar(@s[1]));
(*$else *)
RemoteHost:=Winsock.GetHostByName(PChar(hostname));
(*$endif *)
(*$endif *)
(*@///000000090C*)
if (RemoteHost=NIL) or (RemoteHost^.h_length<=0) then begin
Result:=ip_address;
EXIT; (* host not found *)
end
else
ip_address:=longint(pointer(RemoteHost^.h_addr_list^)^);
(* use the first address given *)
end;
end;
except
ip_address:=INVALID_IP_ADDRESS;
end;
Result:=ip_address;
end;
function IP2String(IPAddr:longint):string;
begin //IP地址转为字符串值
IPAddr:=winsock.ntohl(IPAddr);
result:= inttostr(IPAddr shr 24)+'.'+
inttostr((IPAddr shr 16) and $ff)+'.'+
inttostr((IPAddr shr 8) and $ff)+'.'+
inttostr(IPAddr and $ff);
end;
//------------------------------------------------------------------------------
{ begin TfgPing对象 }
constructor TfgPing.Create(AOwner:TComponent);
var WSAData:TWSAData;
begin
inherited Create(AOwner);
//2为所需winsock.dll版本号
WSAStartup(2,WSAData);
{ if (WSAStartup(MAKEWORD(2,0),WSAData)<>0) then;
raise Exception.Create('Winsock version error!');}
hIcmpDll:=LoadLibrary('icmp.dll');
if hIcmpDll<>0 then
begin //加载
@ICMPCreateFile:=GetProcAddress(hICMPDll,'IcmpCreateFile');
@IcmpCloseHandle:=GetProcAddress(hICMPDll,'IcmpCloseHandle');
@IcmpSendEcho:=GetProcAddress(hICMPDll,'IcmpSendEcho');
end
else
raise Exception.Create('Load icmp.dll fail!');
hICMP:=IcmpCreateFile;
if hICMP=INVALID_HANDLE_VALUE then
raise Exception.Create('Create ICMP Failed!');
f_Status:='';
f_Timeout:=5000;
f_TTL:=64;
f_Host:='127.0.0.1';
f_CheckStr:='Ping Address';
end;
destructor TfgPing.Destroy;
begin
IcmpCloseHandle(hIcmp);
WSACleanup;
if hIcmpDll<>0 then FreeLibrary(hIcmpDll);
inherited Destroy;
end;
procedure TfgPing.SetStatus(Value:string);
begin
f_Status:=Value;
if Assigned(f_PingStatus) then
f_PingStatus(f_Status);
end;
function TfgPing.Ping:boolean;
var IPOpt:TIPOptionInfomation;
FIPAddress
WORD;
pReqData,pRevData
Char;
pIPE
IcmpEchoReply;
FSize
WORD;
MyString:string;
BufferSize
WORD;
temp:integer;
begin
Result:=false;
if f_Pinging then exit;
f_host:=Trim(f_host);
if f_host='' then raise Exception.Create('IP Empty!');
FIPAddress:=HostName2IP(f_host); //获取实际地址
f_IP:=IP2String(FIPAddress); //解析主机名为IP
if FIPAddress=INADDR_NONE then
begin
//raise Exception.Create('Invalid IP Address!');
OnPing(false,'',0,0,0);
exit;
end;
Status:='Ping……';
//计算包大小
FSize:=40;
BufferSize:=SizeOf(TICMPEchoReply)+FSize;
GetMem(pRevData,FSize);
GetMem(pIPE,BufferSize);
//数据准备
FillChar(pIPE^,SizeOf(pIPE^),0);
pIPE^.Data:=pRevData;
MyString:=f_CheckStr;
pReqData:=PChar(MyString);
FillChar(IPOpt,SizeOf(IPOpt),0);
IPOpt.TTL:=f_TTL;
f_Pinging:=true;
try
temp:=IcmpSendEcho(hICMP,FIPAddress,pReqData,Length(MyString),@IPOpt,pIPE,BufferSize,f_Timeout);
finally
f_Pinging:=false;
end;
try
if temp=0 then
begin
Status:='Failure!';
OnPing(false,f_IP,0,0,0);
end
else
begin
if pReqData^=pIPE^.Options.OptionsData^ then
begin
if Assigned(OnPing) then
begin
Status:='Success!';
OnPing(true,f_IP,pIPE^.DataSize,pIPE^.RTT,pIPE^.Options.TTL);
Result:=true;
end;
end;
end;
finally
FreeMem(pRevData);
FreeMem(pIPE);
end;
end;
{ end TfgPing对象 }
//------------------------------------------------------------------------------
end.