- 註冊時間
 - 2006-3-13 
 - 最後登錄
 - 2025-7-23 
 - 在線時間
 - 675 小時 
 - 閱讀權限
 - 200 
 - 積分
 - 417 
 - 帖子
 - 1109 
 - 精華
 - 0 
 - UID
 - 2 
  
 
 
 
    
 | 
 
网络通讯中经常需要确定远程主机是否存活,以决定下一部进行的操作。可以直接使用 ICMP 协议来实现,但是要考虑许多协议细节,实现起来比较麻烦。Windows 自带的 ICMP 库里有现成的函数可以使用,只要在使用前填充相应的数据结构就可以了。  
 
以下是要使用的数据结构。这些结构 MSDN 里有 C 形式的声明,这里给出的是 Delphi 的形式。 
- //用到的协议数据结构
 
 - PIPOptionInfo = ^TIPOptionInfo; // IP 头选项
 
 - TIPOptionInfo = packed record
 
 -   TTL: Byte;//存活时间
 
 -   TOS: Byte;//Type of Service,请求类型
 
 -   Flags: Byte;//标志
 
 -   OptionsSize: Byte;//选项长度
 
 -   OptionsData: PChar;//选项数据
 
 - end;
 
 - PIcmpEchoReply = ^TIcmpEchoReply;
 
 - TIcmpEchoReply = packed record // ICMP 返回信息
 
 -   Address: DWORD;//IP地址
 
 -   Status: DWORD;//状态
 
 -   RTT: DWORD;
 
 -   DataSize: Word;//数据长度
 
 -   Reserved: Word;//保留
 
 -   Data: Pointer;//数据
 
 -   Options: TIPOptionInfo;//选项区
 
 - end;
 
  
- //动态库中的函数声明
 
 - TIcmpCreateFile = function: THandle; stdcall; //创建ICMP句柄
 
 - TIcmpCloseHandle = function(IcmpHandle: THandle): Boolean; stdcall; //关闭ICMP句柄
 
 - TIcmpSendEcho = function(IcmpHandle:THandle; DestinationAddress:DWORD;
 
 - RequestData:Pointer; RequestSize:Word; RequestOptions:PIPOptionInfo;
 
 - ReplyBuffer:Pointer; ReplySize:DWord; Timeout:DWord):DWord; stdcall;//发送ICMP探测数据报
 
  
- //要用到的变量声明
 
 - hICMPDll,hICMP:THandle;
 
 - wsaData:TWSADATA;
 
 - ICMPCreateFile: TICMPCreateFile;
 
 - IcmpCloseHandle: TIcmpCloseHandle;
 
 - IcmpSendEcho:TIcmpSendEcho;
 
  
- //destip: 要探测的远程地址,形如 192.168.1.1
 
 - procedure f_CheckOnline(destip:string);
 
 - var
 
 -   IPOpt:TIPOptionInfo;// 发包的 IP 选项
 
 -   IPAddr:DWORD;
 
 -   pReqData,pRevData:PChar;
 
 -   pIPE:PIcmpEchoReply;// ICMP Echo 回复缓冲区
 
 -   FSize: DWORD;
 
 -   MyString:string;
 
 -   FTimeOut:DWORD;
 
 -   BufferSize:DWORD;
 
 -   i:integer;
 
 - begin
 
 -   hICMPdll := LoadLibrary('icmp.dll'); //调取icmp 动态库
 
 -   if hICMPDll<>NULL then
 
 -   begin
 
 -     WSAStartup($101,wsaData);//初始化网络协议栈
 
 -     @ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile'); //取动态库中的导出函数
 
 -     @IcmpCloseHandle := GetProcAddress(hICMPdll, 'IcmpCloseHandle');
 
 -     @IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho');
 
 -     hICMP := IcmpCreateFile; //创建 icmp句柄
 
 -     IPAddr:= inet_addr(PChar(destip)); //取要探测的远端主机ip地址
 
  
-     FSize := 40;
 
 -     BufferSize := SizeOf(TICMPEchoReply) + FSize;
 
 -     GetMem(pRevData,FSize);
 
 -     GetMem(pIPE,BufferSize);
 
 -     FillChar(pIPE^, SizeOf(pIPE^), 0);
 
 -     pIPE^.Data := pRevData;
 
 -     MyString := 'Hi, OnLine?';//任意字符串
 
 -     pReqData := PChar(MyString);
 
 -     FillChar(IPOpt, Sizeof(IPOpt), 0);
 
 -     IPOpt.TTL := 64;
 
 -     FTimeOut := 500;//等待时长
 
 -     i := IcmpSendEcho(hICMP, IPAddr, pReqData, Length(MyString), @IPOpt, pIPE, BufferSize, FTimeOut);//如果有返回,返回值表示收到的回复的个数。如果为0表示没有回复,主机无法到达
 
 -     FreeMem(pRevData);
 
 -     FreeMem(pIPE);
 
 -     IcmpCloseHandle(hicmp);
 
 -     FreeLibrary(hICMPdll);//释放动态库
 
 -     WSAcleanup();//清理协议栈
 
 -   end;
 
 - end;
 
  複製代碼 |   
 
  
 |