一段简单的代码,调用 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,这个常识就不说了。
2 条评论
沙发空缺中,还不快抢~