Implementing PING Without Using Raw Sockets
若不用 Indy 的 TIdIcmpClient 元件,可藉 Winsock 1.1 的 icmp.dll 開發;適 XP 環境,以 Delphi7 開發
注意:執行程式需要具有系統管理員權限
新增一個 unit 檔,檔名為 raw_ping.pas
unit raw_ping; interface uses Windows, SysUtils, Classes; type TSunB = packed record s_b1, s_b2, s_b3, s_b4: byte; end; TSunW = packed record s_w1, s_w2: word; end; PIPAddr = ^TIPAddr; TIPAddr = record case integer of 0: (S_un_b: TSunB); 1: (S_un_w: TSunW); 2: (S_addr: longword); end; IPAddr = TIPAddr; function IcmpCreateFile: THandle; stdcall; external 'icmp.dll'; function IcmpCloseHandle(icmpHandle: THandle): boolean; stdcall; external 'icmp.dll'; function IcmpSendEcho(IcmpHandle: THandle; DestinationAddress: IPAddr; RequestData: Pointer; RequestSize: Smallint; RequestOptions: pointer; ReplyBuffer: Pointer; ReplySize: DWORD; Timeout: DWORD): DWORD; stdcall; external 'icmp.dll'; function Ping(InetAddress: string): boolean; implementation uses WinSock; function Fetch(var AInput: string; const ADelim: string=' '; const ADelete: Boolean=true): string; var iPos: Integer; begin if ADelim=#0 then begin // AnsiPos does not work with #0 iPos := Pos(ADelim, AInput); end else begin iPos := Pos(ADelim, AInput); end; if iPos=0 then begin Result := AInput; if ADelete then begin AInput := ''; end; end else begin result := Copy(AInput, 1, iPos - 1); if ADelete then begin Delete(AInput, 1, iPos + Length(ADelim) - 1); end; end; end; procedure TranslateStringToTInAddr(AIP: string; var AInAddr); var phe: PHostEnt; pac: PChar; GInitData: TWSAData; begin WSAStartup($101, GInitData); try phe := GetHostByName(PChar(AIP)); if Assigned(phe) then begin pac := phe^.h_addr_list^; if Assigned(pac) then begin with TIPAddr(AInAddr).S_un_b do begin s_b1 := Byte(pac[0]); s_b2 := Byte(pac[1]); s_b3 := Byte(pac[2]); s_b4 := Byte(pac[3]); end; end else begin raise Exception.Create('Error getting IP from HostName'); end; end else begin raise Exception.Create('Error getting HostName'); end; except FillChar(AInAddr, SizeOf(AInAddr), #0); end; WSACleanup; end; function Ping(InetAddress: string): boolean; var Handle: THandle; InAddr: IPAddr; DW: DWORD; rep: array[1..128] of byte; begin result := false; Handle := IcmpCreateFile; if (Handle=INVALID_HANDLE_VALUE) then Exit; TranslateStringToTInAddr(InetAddress, InAddr); DW := IcmpSendEcho(Handle, InAddr, nil, 0, nil, @rep, 128, 0); Result := (DW<>0); IcmpCloseHandle(Handle); end; end.
在 Form 放 1 個 Edit 和 1 個 Button
... ... implementation // 注意這行 uses raw_ping; {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin If raw_Ping.Ping(Edit1.Text) then ShowMessage('ping 得到 '+Edit1.Text) else ShowMessage('ping 不到'); end;
相關筆記 ----
【Delphi】以 Indy TIdIcmpClient 去 ping 網路設備
【Delphi】以 WMI 方式 ping 網路設備
沒有留言:
張貼留言