delphi 调用 Windows API Ping 指定的主机


一段简单的代码,调用 API 来实现 PING 指定的主机。

[C++ Builder 版]

#include <iphlpapi.h>

#include <icmpapi.h>

#pragma comment(lib, "iphlpapi.lib")

#pragma comment(lib, "ws2_32.lib")

// ---------------------------------------------------------------------------


int __fastcall Ping(const AnsiString AHost) {

HANDLE hIcmp = IcmpCreateFile();

int ARetVal;

if (hIcmp != INVALID_HANDLE_VALUE) {

try {

char AData[32] = "ICMP Data";

DWORD Addr = inet_addr(AHost.c_str());

if (Addr == INADDR_NONE) {

hostent *ent = gethostbyname(AHost.c_str());

if (ent && (ent->h_addrtype == AF_INET)) {

Addr=*((DWORD *)ent->h_addr_list[0]);

}

else {

ARetVal = GetLastError();

return ARetVal;

}

}

DWORD AReplySize = sizeof(ICMP_ECHO_REPLY)+sizeof(AData);

char AReply[sizeof(ICMP_ECHO_REPLY)+sizeof(AData)];

ARetVal = IcmpSendEcho(hIcmp, Addr, &AData, sizeof(AData), NULL,

AReply, AReplySize, 1000);

if (ARetVal == 0)

ARetVal = GetLastError();

else

ARetVal = 0;

}

__finally {

IcmpCloseHandle(hIcmp);

}

}

else

ARetVal = GetLastError();

return ARetVal;

}




[Delphi 版]

uses iphlpapi, winsock;


const

  ICMPDLL = 'icmp.dll';


type

  PIPOptionInformation = ^TIPOptionInformation;


  TIPOptionInformation = packed record

    TTL: Byte;

    TOS: Byte;

    Flags: Byte;

    OptionsSize: Byte;

    OptionsData: PChar;

  end;


  ICMP_ECHO_REPLY = packed record

    Address: DWORD;

    Status: DWORD;

    RTT: DWORD;

    DataSize: Word;

    Reserved: Word;

    Data: Pointer;

    Options: TIPOptionInformation;

  end;


  TIcmpEchoReply = ICMP_ECHO_REPLY;

  PIcmpEchoReply = ^TIcmpEchoReply;


function IcmpCreateFile: THandle; stdcall; external ICMPDLL;

function IcmpCloseHandle(IcmpHandle: THandle): Boolean; stdcall;

  external ICMPDLL;

function IcmpSendEcho(IcmpHandle: THandle; DestinationAddress: DWORD;

  RequestData: Pointer; RequestSize: Word; RequestOptions: PIPOptionInformation;

  ReplyBuffer: Pointer; ReplySize: DWORD; Timeout: DWORD): DWORD; stdcall;

  external ICMPDLL;


// ---------------------------------------------------------------------------


function Ping(const AHost: AnsiString): Integer;

var

  hIcmp: THandle;

  AData: array [0 .. 31] of Byte;

  AReply: array [0 .. sizeof(ICMP_ECHO_REPLY) + 31] of Byte;

  Addr: Cardinal;

  ent: PHostEnt;

  AReplySize: Integer;

begin

  hIcmp := IcmpCreateFile;

  if hIcmp <> INVALID_HANDLE_VALUE then

  begin

    try

      Addr := inet_addr(PAnsiChar(AHost));

      if Addr = INADDR_NONE then

      begin

        ent := gethostbyname(PAnsiChar(AHost));

        if Assigned(ent) and (ent.h_addrtype = AF_INET) then

          Addr := PCardinal(ent.h_addr_list[0])^

        else

        begin

          Result := GetLastError;

          Exit;

        end;      

      end;

      AReplySize := sizeof(ICMP_ECHO_REPLY) + sizeof(AData);

      Result := IcmpSendEcho(hIcmp, Addr, @AData[0], sizeof(AData), nil,

        @AReply[0], AReplySize, 1000);

      if Result = 0 then

        Result := GetLastError()

      else

        Result := 0;

    finally

      IcmpCloseHandle(hIcmp);

    end;

  end

  else

    Result := GetLastError();

end;

成功,返回0,失败返回错误代码,参数可以是主机名或IP地址。如果是主机名,则会解析成IP地址才能。

注意无论那个版本,都要先调用 WSAStartup,在不需要时调用WSACleanup,这个常识就不说了。


联系电话:
020-00000000
联系电话:
020-00000000
联系电话:
020-12345678