首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi ICMP Ping 實作:呼叫系統 icmp.dll 實現無元件跨平台主機存活檢測

     編輯:Delphi

需在程式中快速檢測遠端主機是否在線?無需 Indy、ICS 等第三方元件,Windows 核心 icmp.dll 內建 IcmpCreateFile、IcmpSendEcho、IcmpCloseHandle 三大 API,動態載入即可實現標準 ICMP Echo Request/Reply,支援 IPv4、自定義封包大小、TTL、逾時。本文提供完整 Delphi 封裝代碼與結構定義。

核心結構定義 (對應 MSDN C 結構)


type
  PIPOptionInfo = ^TIPOptionInfo;
  TIPOptionInfo = packed record
    TTL: Byte;       // Time To Live
    TOS: Byte;       // Type of Service
    Flags: Byte;
    OptionsSize: Byte;
    OptionsData: PChar;
  end;

  PIcmpEchoReply = ^TIcmpEchoReply;
  TIcmpEchoReply = packed record
    Address: DWORD;   // 回應者 IP
    Status: DWORD;    // IP_SUCCESS=0 成功
    RTT: DWORD;       // 往返延遲 (毫秒)
    DataSize: Word;   // 回應資料長度
    Reserved: Word;
    Data: Pointer;    // 回應資料指標
    Options: TIPOptionInfo;
  end;

動態載入函數指標


type
  TIcmpCreateFile = function: THandle; stdcall;
  TIcmpCloseHandle = function(h: THandle): Boolean; stdcall;
  TIcmpSendEcho = function(
    h: THandle; DestAddr: DWORD; ReqData: Pointer; ReqSize: Word;
    ReqOpt: PIPOptionInfo; ReplyBuf: Pointer; ReplySize: DWORD; Timeout: DWORD
  ): DWORD; stdcall;

var
  hIcmpDll: THandle;
  IcmpCreateFile: TIcmpCreateFile;
  IcmpCloseHandle: TIcmpCloseHandle;
  IcmpSendEcho: TIcmpSendEcho;

完整 Ping 函數


procedure CheckHostOnline(DestIP: String);
var
  IPOpt: TIPOptionInfo;
  IPAddr: DWORD;
  ReqData, RepData: PChar;
  RepBuf: PIcmpEchoReply;
  BufSize, Timeout: DWORD;
  I: Integer;
  Msg: String;
begin
  // 1. 載入 icmp.dll
  hIcmpDll := LoadLibrary('icmp.dll');
  if hIcmpDll = 0 then Exit;

  // 2. 取得函數位址
  @IcmpCreateFile  := GetProcAddress(hIcmpDll, 'IcmpCreateFile');
  @IcmpCloseHandle := GetProcAddress(hIcmpDll, 'IcmpCloseHandle');
  @IcmpSendEcho    := GetProcAddress(hIcmpDll, 'IcmpSendEcho');
  if (@IcmpCreateFile = nil) or (@IcmpSendEcho = nil) then begin
    FreeLibrary(hIcmpDll); Exit;
  end;

  // 3. 初始化 Winsock (舊版需呼叫)
  WSAStartup($101, WSAData);

  // 4. 建立 ICMP 句柄
  hIcmp := IcmpCreateFile;

  // 5. 解析目標 IP
  IPAddr := inet_addr(PChar(DestIP)); // 需 Winsock 單元

  // 6. 準備請求/回應緩衝區
  Msg := 'Hello, Ping!';
  ReqData := PChar(Msg);
  GetMem(RepData, 64);
  BufSize := SizeOf(TIcmpEchoReply) + 64;
  GetMem(RepBuf, BufSize);
  FillChar(RepBuf^, BufSize, 0);
  RepBuf.Data := RepData;

  // 7. 設定 IP 選項
  FillChar(IPOpt, SizeOf(IPOpt), 0);
  IPOpt.TTL := 64;
  Timeout := 1000; // 1 秒逾時

  // 8. 發送 Echo Request
  I := IcmpSendEcho(hIcmp, IPAddr, ReqData, Length(Msg), @IPOpt, RepBuf, BufSize, Timeout);

  // 9. 判斷結果
  if I > 0 then begin
    if RepBuf.Status = 0 then // IP_SUCCESS
      ShowMessage(Format('主機 %s 回應正常,RTT=%d ms', [DestIP, RepBuf.RTT]))
    else
      ShowMessage(Format('主機 %s 回應錯誤,狀態碼=%d', [DestIP, RepBuf.Status]));
  end else
    ShowMessage(Format('主機 %s 無回應 (逾時或不可達)', [DestIP]));

  // 10. 清理資源
  FreeMem(RepData); FreeMem(RepBuf);
  IcmpCloseHandle(hIcmp);
  FreeLibrary(hIcmpDll);
  WSACleanup;
end;

關鍵參數調整建議

參數建議值說明
TTL64~128跨路由器需足夠 TTL,本地網 32 即可
Timeout500~3000 ms視網路延遲調整,跨國建議 3000+
Request Data Size32~64 bytes過大可能被防火牆丟棄
Reply BufferSizeOf(TIcmpEchoReply) + MaxReplyData必須足夠大否則資料截斷

優缺點對比

方案優點缺點
icmp.dll 動態載入零依賴、系統內建、支援原始 Socket 權限不足環境、極輕量需動態載入代碼、IPv6 不支援、錯誤碼需查表
TIdICMPClient (Indy)封裝完善、事件驅動、支援 IPv6、跨平台引入龐大 Indy 元件、需管理員權限建立 Raw Socket
ShellExecute ping.exe最簡單需解析文字輸出、無法獲取精確 RTT、有視窗閃爍

適用場景

  • 安裝程式檢測資料庫伺服器可用性。
  • 監控工具定期巡檢伺服器叢集。
  • 嵌入式/精簡版應用無法引入 Indy 時。
  • 需精確 RTT 統計網路品質。

掌握 icmp.dll 動態呼叫,讓你的 Delphi 程式擁有「系統級網路診斷能力」,無需任何第三方依賴。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved