2000,Xp,Nt系统下实现!unit Link; interface function GateWay:string; procedure IfLink;implementation uses main,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,Registry, Grids; function GateWay:string; var Reg :TRegistry; MyStr : TStrings; buffer : array[0..1024] of byte; i:integer; info:TRegKeyInfo ; str:string; begin Result:='0'; Reg :=TRegistry.Create; Mystr:=Tstringlist.Create; try Reg.RootKey :=HKEY_LOCAL_MACHINE; if Reg.OpenKey('SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards',false) then begin if reg.GetKeyInfo(info) then begin reg.GetKeyNames(mystr); str:='SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards\'+Mystr.Strings[0]; end; end; finally Reg.CloseKey; Mystr.Free; Reg.RootKey :=HKEY_LOCAL_MACHINE; if reg.OpenKey(str,false) then begin str:=reg.ReadString('ServiceName'); end; Reg.CloseKey; Reg.RootKey :=HKEY_LOCAL_MACHINE; if reg.OpenKey('SYSTEM\CurrentControlSet\Services\'+str+'\Parameters\Tcpip\',false) then begin str:=''; for i:= 1 to reg.ReadBinaryData('defaultGateway',buffer,sizeof(buffer)) do str:=str+chr(dword(buffer[i-1])); end; if str=chr(0) then begin str:=''; for i:= 1 to reg.ReadBinaryData('DhcpDefaultGateway',buffer,sizeof(buffer)) do str:=str+chr(dword(buffer[i-1])); end; Reg.CloseKey; reg.Free; if (str=char(0)) or (str='') then str:='66.218.71.88'; result:=str; end; end; procedure IfLink;begin with mainForm do begin ICMP.ReceiveTimeout:=10; try ICMP.Host := GateWay; ICMP.Ping; linklabel.caption:='正常'; linkLabel.Font.Color:=clGreen; except linklabel.caption:='断开'; mainform.linkLabel.Font.Color:=clred; end; end; end;end.
许多人经常利用Windows中的两条DOS命令(Ping和Tracert)来测试网络状态,其原理是通过向探测的节点端口发送数据包请求,然后从该端口是否应答来判断网络是否畅通。其实,在Windows的System目录下有一个Icmp.dll文件,该动态链接库提供了ICMP协议的所有功能,通过对该动态链接库的调用可以完成发送请求和接收应答。因此,可以利用该动态链接库实现专线状态的探测。
Icmp.dll文件内的主要调用函数如下:
● IcmpCreateFile: 打开一个句柄,通过该句柄发送ICMP的请求报文;
● IcmpCloseHandle: 关闭通过IcmpCreateFile函数打开的句柄;
● IcmpSendEcho:通过打开的句柄发送ICMP请求,在超时或接收到应答报文后返回。 编程实现
首先构造节点库,然后通过调用ICMP协议,向测试端口发送请求,如果接收到该端口的应答,则状态为“正常”,否则,状态为“中断”。
1. 初始化WinSock,调入Icmp.dll库 var wsadata: TWSAData; begin if WSAStartup($101,wsadata) <> 0 then begin ShowMessage(‘Error initialising WinSock’); halt; end; hICMPlib ∶= loadlibrary(icmpDLL); if hICMPlib <> null then begin @ICMPCreateFile ∶= GetProcAddress(hICMPlib, ‘IcmpCreateFile’); @IcmpCloseHandle∶= GetProcAddress(hICMPlib, ‘IcmpCloseHandle’); @IcmpSendEcho∶= GetProcAddress(hICMPlib, ‘IcmpSendEcho’); if (@ICMPCreateFile = Nil) or (@IcmpCloseHandle = Nil) or (@IcmpSendEcho=Nil) then begin ShowMessage(‘Error loading dll functions’); halt; end; hICMP ∶= IcmpCreateFile; if hICMP=INVALID_HANDLE_VALUE then begin ShowMessage(‘Unable to get ping handle’); halt; end; end; else begin ShowMessage(‘Unable to register’+ icmpDLL); halt; end; end; 2. 使用定时器启动探测
在测试中,如果端口状态正常,则net_stat=0;状态异常则net_stat=1,并显示“中断”,系统响铃报警。对节点表中所有节点进行测试的主要代码如下:
//取得欲测试端口的IP地址 net_ip∶=Table1. FieldByName(‘对端IP’). asstring; //调用端口测试 Test(Sender); if net_stat=0 then begin Table1. FieldByName(‘状态’). asstring∶=‘中断’; //端口异常,则net=1 if net=0 then net∶=1; end else Table1. FieldByName(‘状态’). asstring∶=‘正常’; //整表测试后,如有异常的端口,则10次响铃报警 if net=1 then FOR I∶=1 TO 10 DO PlaySound(‘RINGIN’, 0, SND_RESOURCE); 3. 探测指定的端口:Test(Sender) const Size = 56; TimeOut = 3000; var Address: DWord; HostName, HostIP: String; Phe: PHostEnt; BufferSize, nPkts: Integer; pReqData, pData: Pointer; pIPE: PIcmpEchoReply; IPOpt: TIPOptionInformation; begin //将存储字符串的地址转化为标准的网络IP地址 ddress ∶= inet_addr(PChar(net_ip)); //取得测试端口的句柄 Phe ∶= GetHostByAddr(@Address, 4, PF_INET); // 设定一个缓冲区,填充指定数据作为待发送的数据包 BufferSize ∶= SizeOf(TICMPEchoReply) + Size; GetMem(pReqData, Size); GetMem(pData, Size); GetMem(pIPE, BufferSize); FillChar(pReqData^, Size, $AA); pIPE^.Data ∶= pData; FillChar(IPOpt, SizeOf(IPOpt), 0); IPOpt.TTL ∶= 64; //通过打开的句柄,发送ICMP数据包请求,在超时或接收应答报文后返回 NPkts ∶= IcmpSendEcho(hICMP, Address, pReqData, Size, @IPOpt, pIPE, BufferSize, TimeOut); //根据是否从测试端口返回应答报文,判断网络状态 if NPkts = 0 then net_stat∶=0 else begin HostIP ∶= StrPas(inet_ntoa(TInAddr(pIPE^.Address))); if trim(HostIP)=trim(net_ip) then net_stat∶=1 else net_stat∶=0; end; //释放变量 FreeMem(pIPE); FreeMem(pData); FreeMem (pReqData); end;
4. 关闭探测程序
//释放ICMP
IcmpCloseHandle(hICMP);
FreeLibrary(hICMPlib);
//释放WinSock
if WSACleanup <> 0 then ShowMessage(‘Error freeing WinSock’); 完善程序
上述程序仅提供了基本的网络探测方法,为了更好地体现网络状态和处理情况,可以对此程序进一步完善:
1. 再建两个表:
● 故障记录和处理表: 在探测中将故障节点记录保存,并记录故障处理情况;
● 探测间隔表:灵活设置探测时间间隔。
2. 添加节点库维护模块。
3. 对于探测模块的显示进行改造,使故障节点呈现报警色(如红色)。
<<<转载的文章>>>作者:寒易
你可以去www.codelphi.com里面找(技术锦囊->网络)
里面就有这么一个东东
如果是ping,它应该ping谁?网络上不见得就有其它的机器,有可能只有一台机器的。
interface
function GateWay:string;
procedure IfLink;implementation uses main,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls,Registry,
Grids;
function GateWay:string;
var
Reg :TRegistry;
MyStr : TStrings;
buffer : array[0..1024] of byte;
i:integer;
info:TRegKeyInfo ;
str:string;
begin
Result:='0';
Reg :=TRegistry.Create;
Mystr:=Tstringlist.Create;
try
Reg.RootKey :=HKEY_LOCAL_MACHINE;
if Reg.OpenKey('SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards',false) then
begin
if reg.GetKeyInfo(info) then
begin reg.GetKeyNames(mystr);
str:='SOFTWARE\Microsoft\Windows NT\CurrentVersion\NetworkCards\'+Mystr.Strings[0];
end;
end;
finally
Reg.CloseKey;
Mystr.Free;
Reg.RootKey :=HKEY_LOCAL_MACHINE;
if reg.OpenKey(str,false) then
begin
str:=reg.ReadString('ServiceName');
end;
Reg.CloseKey;
Reg.RootKey :=HKEY_LOCAL_MACHINE;
if reg.OpenKey('SYSTEM\CurrentControlSet\Services\'+str+'\Parameters\Tcpip\',false) then
begin
str:='';
for i:= 1 to reg.ReadBinaryData('defaultGateway',buffer,sizeof(buffer)) do
str:=str+chr(dword(buffer[i-1]));
end;
if str=chr(0) then
begin
str:='';
for i:= 1 to reg.ReadBinaryData('DhcpDefaultGateway',buffer,sizeof(buffer)) do
str:=str+chr(dword(buffer[i-1]));
end; Reg.CloseKey;
reg.Free;
if (str=char(0)) or (str='') then
str:='66.218.71.88';
result:=str;
end;
end;
procedure IfLink;begin
with mainForm do begin ICMP.ReceiveTimeout:=10;
try
ICMP.Host := GateWay;
ICMP.Ping; linklabel.caption:='正常';
linkLabel.Font.Color:=clGreen;
except
linklabel.caption:='断开';
mainform.linkLabel.Font.Color:=clred;
end;
end;
end;end.