- 註冊時間
 - 2006-3-13 
 - 最後登錄
 - 2025-7-23 
 - 在線時間
 - 675 小時 
 - 閱讀權限
 - 200 
 - 積分
 - 417 
 - 帖子
 - 1109 
 - 精華
 - 0 
 - UID
 - 2 
  
 
 
 
    
 | 
 
范智鑫 王毅燕  
 
随着计算机用户的增多,计算机网络越来越复杂,如何进行实时的网络检测成为网管人员关心的问题。实时监测可以在最早的时间内发现问题,避免网络长时间继线。本文介绍一种利用Delphi编写应用程序实现专线状态探测的方法。 
  
实现原理  
许多人经常利用Windows中的两条DOS命令(Ping和Tracert)来测试网络状态,其原理是通过向探测的节点端口发送数据包请求,然后从该端口是否应答来判断网络是否畅通。其实,在Windows的System目录下有一个Icmp.dll文件,该动态链接库提供了ICMP协议的所有功能,通过对该动态链接库的调用可以完成发送请求和接收应答。因此,可以利用该动态链接库实现专线状态的探测。  
 
Icmp.dll文件内的主要调用函数如下:  
● IcmpCreateFile: 打开一个句柄,通过该句柄发送ICMP的请求报文;  
● IcmpCloseHandle: 关闭通过IcmpCreateFile函数打开的句柄;  
● IcmpSendEcho:通过打开的句柄发送ICMP请求,在超时或接收到应答报文后返回。  
 
编程实现  
首先构造节点库(如图1所示),然后通过调用ICMP协议,向测试端口发送请求,如果接收到该端口的应答,则状态为“正常”,否则,状态为“中断”。  
 
图1  
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地址
 
 -   Address := 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. 对于探测模块的显示进行改造,使故障节点呈现报警色(如红色)。 |   
 
  
 |