[轉貼]Implementing PING without using raw sockets

有關Delphi 的語法, 程式, 等
回覆文章
頭像
tim
文章: 1379
註冊時間: 2008年 11月 26日, 00:49

[轉貼]Implementing PING without using raw sockets

文章 tim »

http://delphi.about.com/library/weekly/aa081503a.htm

PING
Windows supports an Internet Control Message Protocol (ICMP) to determine whether or not a particular host is available.
ICMP is a network layer protocol that delivers flow control, error messages, routing, and other data between Internet hosts. ICMP is primarily used by application developers for a network ping.
A ping is the process of sending an echo message to an IP address and reading the reply to verify a connection between TCP/IP hosts. If you are writing new application you will be better to use the Winsock 2 raw sockets support, implemented in Indy, for example.

Please note, however, that for Windows NT and Windows 2000 implementations, Raw Sockets are subject to security checks and are accessible only to members of the administrator's group. Icmp.dll provides functionality that allows developers to write Internet ping applications on Windows systems without Winsock 2 support.
Note that the Winsock 1.1 WSAStartup function must be called prior to using the functions exposed by ICMP.DLL. If you do not do this, the first call to IcmpSendEcho will fail with error 10091 (WSASYSNOTREADY).

1) Example 1 (code snippet):

代碼: 選擇全部

uses Ping;
...
const ADP_IP = '208.185.127.40'; (* http://delphi.about.com *)
begin
If  Ping.Ping(ADP_IP) then
  ShowMessage('About Delphi Programming reachable!');
end;
2) Here's another, console mode Delphi program, that uses the Ping unit .. download.

And, the Ping unit's source:

代碼: 選擇全部


unit 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.
多多留言, 整理文章, 把經驗累積下來.....
回覆文章