Articles Implementing PING Without Using Raw Sockets by Zarko Gajic

emailx45

Местный
Регистрация
5 Май 2008
Сообщения
3,571
Реакции
2,438
Credits
573
Implementing PING Without Using Raw Sockets
Zarko Gajic - April 03, 2019
[SHOWTOGROUPS=4,20]
Internet PINGs Using Delphi and Icmp.dll (this DLL can be founded in C:\Windows\System32 or SysWOW64 in 64bit edition)

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.

What Is a 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 a 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).

Below you can find the Ping unit's source code. Here are two examples of usage.

Example 1: Code Snippet
Код:
uses
   Ping;

const
    ADP_IP = 'YOUR_IP_FOR_TEST_HERE_or_YOUR_URL_DOMAIN'; // www.google.com or aaa.bbb.ccc.ddd
begin
   If  Ping.Ping(ADP_IP) then
       ShowMessage('Your IP is reachable!')
   else
       ShowMessage('Your IP is not reachable!')
end;

Example 2: Console Mode Delphi Program

Our next example is a console mode Delphi program that uses the Ping unit: . Here's 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
  lHostEnt    : PHostEnt;
  lAddressList: PAnsiChar;
  lInitWSAData: TWSAData;
begin
  lHostEnt     := nil;
  lAddressList := nil;
  //
  WSAStartup($101, lInitWSAData);
  //
  try
    try
      lHostEnt := GetHostByName(PAnsiChar(AIP));
      //
      if (lHostEnt = nil) then
        raise Exception.Create('Error getting HostName');
      //
      lAddressList := lHostEnt^.h_addr_list^;
      //
      if (lAddressList = nil) then
        raise Exception.Create('Error getting IP from HostName');
      //
      with TIPAddr(AInAddr).S_un_b do
      begin
        s_b1 := Byte(lAddressList[0]);
        s_b2 := Byte(lAddressList[1]);
        s_b3 := Byte(lAddressList[2]);
        s_b4 := Byte(lAddressList[3]);
      end;
    except
      FillChar(AInAddr, SizeOf(AInAddr), #0);
    end;
  finally
    WSACleanup;
  end;
end;

function Ping(InetAddress: string): boolean;
var
  lHandle         : THandle;
  lIPAddressTarget: IPAddr;
  lResult         : DWORD;
  lReplyBuffer    : array [1 .. 128] of byte;
begin
  result := false;
  //
  lHandle := IcmpCreateFile;
  //
  try
    try
      if not(lHandle = INVALID_HANDLE_VALUE) then
      begin
        //
        TranslateStringToTInAddr(InetAddress, lIPAddressTarget);
        //
        // ICMPHandle, IPAddressTarget, RequestData, RequestSize, RequestOptions, ReplyBuffer, ReplySize, Timeout
        lResult := IcmpSendEcho(lHandle, lIPAddressTarget, nil, 0, nil, @lReplyBuffer, 128, 0);
        //
        Result := not(lResult = 0);
      end;
    except
      // result := false;
    end;
  finally
    IcmpCloseHandle(lHandle);
  end;
end;
[/SHOWTOGROUPS]
 
Последнее редактирование: