How can I do that from within Delphi?
Can you give an example?
Main Topics
Browse All TopicsHi,
When I try to check if my PC is connected to the internet, than this function doesn't work with my configuration.
If InternetGetConnectedState(
begin
// Only do this if connected.
end;
My PC is connected like this
PC -> Router -> ADSL modem.
When I'm online everything works fine. But when I shut down my ADSL-modem it still thinks I'm online.
How can I check if there is REALY a connection present?
Thanks, Stef
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
There is also a way using the sens api library set. Please see the TNetwork class that I put together for the following q: http://www.experts-exchang
Regards,
Russell
Answer to: thousandjulys
InetIsOffline always returns False. So this isn't useful in my case.
Answer to: Rlibby
I've Added unit Network to my project and also download the IPHelper from Jedi.
But how do I use them?
1. To determine if there is a connection active
2. To determine the connectiontype (modem, lan)
Can you supply twee buttonclick-events that show usage?
Thank you very much.
Stef
> How can I do that from within Delphi?
> Can you give an example?
Ping without raw sockets
http://www.delphipages.com
TPing component
http://www.torry.net/vcl/i
Hi,
try these functions:
const
NETWORK_ALIVE_LAN = $00000001;
NETWORK_ALIVE_WAN = $00000002;
NETWORK_ALIVE_AOL = $00000004;
function IsNetworkAlive(out Flags: DWORD): BOOL; stdcall;
external 'sensapi.dll' name 'IsNetworkAlive';
function IsDestinationReachable(Des
external 'sensapi.dll' name 'IsDestinationReachableA';
Regards,
Markus
As Markus stated above, the 2 SENS apis (actually, only need one) can be used to determine network connectivity. These are the same functions that my network class uses to determine connectivity and if a site can be reached or not. So, all that is needed to accomplish the 2 requirements:
1.) Determine if connected
2.) If connected, determine connection type
Is this:
var dwFlags: DWORD;
begin
// Determine the current connections
if IsNetworkAlive(dwFlags) then
begin
// Set connection types
if ((dwFlags and NETWORK_ALIVE_LAN) = NETWORK_ALIVE_LAN) then
// Connected via lan
ShowMessage('Connected via LAN')
else
// Connected via lan (or for win 95/98 connected to AOL via ras)
ShowMessage('Connected via Modem');
end
else
ShowMessage('Not connected!');
end;
---------------
Regards,
Russell
>> As Markus stated above, the 2 SENS apis (actually, only need one) can be used to determine network connectivity.
>> These are the same functions that my network class uses to determine connectivity and if a site can be reached or not.
Sorry, I didn't follow your link above and so didn't know that you already put all of this together in a component. BTW, my own component almost looks the same. ;-)
Regards,
Markus
Sorry, should have indicated that the example code I gave was based off from Markus's declaration above. If using my declaration (which was taken from the MSDN) then just preface dwFlags with the @ sign
eg
if IsNetworkAlive(@dwFlags) then
begin
// Set connection types
if ((dwFlags and NETWORK_ALIVE_LAN) = NETWORK_ALIVE_LAN) then
// Connected via lan
ShowMessage('Connected via LAN')
Only difference is my declaration allows the passing of nil, and the other declaration always requires a dword variable to be passed.
Russell
Thanks, the project works..... BUT
It still thinks I am connected to the internet although I'm only connected to my own network.
Probably this function is only checking if there is a connection to an IP-adres, where it should scan all IP's for the local computer and if an IP is detected and this IP is not in the list of the local networkcard then we have an internet connection.
I found a component that will check for just that, but that component can't detect Cable-modemconnections.
Maybe one of you can combine these two.
Here is the code of the component - Thanks to Mark Gauthier
====================
unit INetDetect;
interface
uses
Windows, Messages, Classes, Forms, Winsock, ExtCtrls;
type
TAddrItem = class(TCollectionItem)
public
s: string;
end;
TINetDetect = class(TComponent)
private
FLocalAddrs: TCollection;
FCurrentIP: String;
FHostName: PChar;
FOnline: Boolean;
FEnabled: Boolean;
FDispatchInterval: Cardinal;
FOnChanged: TNotifyEvent;
Timer: TTimer;
function Get(Index: Integer): string;
function GetCount: Integer;
procedure GetLocalIPs;
procedure SetEnabled(Value: Boolean);
procedure SetDispatchInterval(Value:
procedure OnTimer(Sender: TObject);
procedure DoNothingBool(b: boolean);
procedure DoNothingString(s: string);
function GetFHostName: string;
protected
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
property LocalIPs[Index: Integer]: string read Get;
property LocalIPsCount: integer read GetCount;
published
property Enabled: Boolean read FEnabled write SetEnabled;
property DispatchInterval: Cardinal read FDispatchInterval write SetDispatchInterval;
property Online: Boolean read FOnline write DoNothingBool;
property CurrentIP : String read FCurrentIP write DoNothingString;
property OnChanged: TNotifyEvent read FOnChanged write FOnChanged;
property HostName: String read GetFHostName write DoNothingString;
end;
//{$EXTERNALSYM WSAIoctl}
function WSAIoctl( hSocket: TSocket; ControlCode:dword;
InBuf : Pointer; InBufLen:DWord;
OutBuf : Pointer; OutBufLen:DWord;
BytesReturned : PDWord;
lpOverlapped: POverlapped;
lpOverlappedRoutine:pointe
//{$EXTERNALSYM WSASocket}
function WSASocket(Family, sType, Protocol : Integer;
lpProtocolInfo : Pointer;
Group : uint;
dwFlags : DWORD): TSocket; stdcall;
function WSAIoctl; external 'ws2_32.dll' name 'WSAIoctl';
function WSASocket; external 'ws2_32.dll' name 'WSASocketA';
Type
_INTERFACE_INFO = record
iiFlags : ulong; //* Type and status of the interface */
iiAddress : TSockaddr; //* Interface address */
iiBroadcastAddress : TSockaddr; //* Broadcast address */
iiNetmask : TSockaddr; //* Network mask */
end;
Const
IFF_UP = $00000001; //* Interface is up */
IFF_BROADCAST = $00000002; //* Broadcast is supported */
IFF_LOOPBACK = $00000004; //* this is loopback interface */
IFF_POINTTOPOINT = $00000008; //*this is point-to-point interface*/
IFF_MULTICAST = $00000010; //* multicast is supported */
procedure Register;
implementation
uses sysutils;
procedure TINetDetect.DoNothingStrin
procedure TINetDetect.DoNothingBool(
function TINetDetect.GetFHostName: string;
begin
Result := StrPas(FHostName);
end;
constructor TINetDetect.Create(AOwner:
begin
inherited Create(AOwner);
FEnabled := False;
FDispatchInterval := 1000;
Getmem(FHostName, 64);
FLocalAddrs := TCollection.Create(TAddrIt
Timer := TTimer.Create(self);
Timer.Enabled := FEnabled;
Timer.interval := FDispatchInterval;
Timer.OnTimer := OnTimer;
GetLocalIPs;
OnTimer(Self); // Get current status
end;
destructor TINetDetect.Destroy;
begin
FLocalAddrs.Clear;
FLocalAddrs.Free;
Timer.Free;
FreeMem(FHostName);
FEnabled := False;
inherited Destroy;
end;
procedure TINetDetect.GetLocalIPs;
const SIO_GET_INTERFACE_LIST : dword = 1074033791;
var
pAddrInet : TSockAddr;
OutBufLen,
RecvBytes,
i : DWORD;
wsError : Integer;
WSAData : TWSAData;
MySocket : TSocket;
localAddr : Array[1..10] of _INTERFACE_INFO; //up to 10 NICs
begin
wsError := Winsock.WSAStartup(2, WSAData); //winsock 2 or better.
If wsError <> 0 then exit;
Gethostname(FHostName, 64);
MySocket := WSASocket(AF_INET, Sock_DGRAM, IPPROTO_UDP, nil,0,0);
If MySocket = INVALID_SOCKET then exit;
OutBufLen := Sizeof(localAddr);
RecvBytes := OutBufLen;
FillChar(LocalAddr,OutBufL
wsError := WSAIoctl(MySocket,SIO_GET_
if wsError = SOCKET_ERROR then
begin
wsError := WSAGetLastError;
Raise Exception('Socket error:'+IntToStr(wsError))
exit;
end;
for i := 1 to RecvBytes div Sizeof(_Interface_Info) do
begin
pAddrInet := localAddr[i].iiAddress;
With FLocalAddrs.Add as TAddrItem do s:=inet_ntoa(pAddrInet.sin
end;
closesocket(MySocket);
WSACleanup();
end;
procedure TINetDetect.OnTimer(Sender
type
TaPInAddr = Array[0..10] of PInAddr;
PaPInAddr = ^TaPInAddr;
var
phe: PHostEnt;
pptr: PaPInAddr;
I,J: Integer;
GInitData: TWSAData;
NewStatus,
OldStatus : Boolean;
NewIP: string;
IP: string;
Found: Boolean;
begin
Timer.Enabled := false;
WSAStartup($101, GInitData);
GetHostName(FHostName, 64);
phe := GetHostByName(FHostName);
if phe = nil then Exit;
pPtr := PaPInAddr(phe^.h_addr_list
I := 0;
NewIP := '';
NewStatus := False;
OldStatus := FOnline;
while pPtr^[I] <> nil do
begin
IP := inet_ntoa(pptr^[I]^);
Found := false;
For j := 0 to LocalIPsCount-1 do
begin
If (FLocalAddrs.Items[j] as TAddrItem).s = IP then
begin
Found := true;
Break; { Break for }
end;
end;
If Not Found then
begin
// If IP is a new Address where are connected...
NewStatus := true;
NewIP := IP;
Break; { break while }
end;
Inc(I);
end;
WSACleanup;
FCurrentIP := NewIP;
If NewStatus <> OldStatus then
begin
FOnline := NewStatus;
if Assigned(FOnChanged) then FOnChanged(self);
end;
Timer.Enabled := true;
end;
procedure TINetDetect.SetEnabled(Val
begin
if Value <> FEnabled then
begin
FEnabled := Value;
Timer.Enabled := Value;
end;
end;
procedure TINetDetect.SetDispatchInt
begin
if Value <> FDispatchInterval then
begin
FDispatchInterval := Value;
Timer.Interval := Value;
end;
end;
function TINetDetect.Get(Index: Integer): string;
begin
If (FLocalAddrs.Count > 0) and (Index In[0..FLocalAddrs.Count]) then
Result := (FLocalAddrs.Items[Index] as TAddrItem).S ;
end;
function TINetDetect.GetCount: Integer;
begin
Result := FLocalAddrs.Count;
end;
procedure Register;
begin
RegisterComponents('Intern
end;
end.
It would be much simpler to use the IsDestinationReachable (which can also provide a much better test)
type
tagQOCINFO = packed record
dwSize: DWORD;
dwFlags: DWORD;
dwInSpeed: DWORD;
dwOutSpeed: DWORD;
end;
QOCINFO = tagQOCINFO;
TQOCInfo = QOCINFO;
PQOCInfo = ^TQOCInfo;
function IsDestinationReachable(lps
usage:
var qocData: TQOCInfo;
begin
// Set the size for quality of connection structure
qocData.dwSize:=SizeOf(TQO
// Check to see if destination can be reached
if IsDestinationReachable('ww
begin
// Destination can be reached
ShowMessage('Destination reachable');
end;
end;
----
Russell
Stef,
The component you listed above does not work; at least not for MANY configurations. For example, when connected to the internet and I start my program that uses the component code. The following happens:
Two IP addresses are listed for the 2 interfaces (this is expected)
--------------------------
10.xx.xx.xx - My network ip address
0.0.0.0 - My loopback address
The gethostbyname call returns a PHostEnt pointer, and in it exists one IP address, which is the 10.xx.xx.xx from above. According to the component I am "offline", but in actuality I AM online. When I unplug my network cable, the IP address for the gethostbyname call reverts to a local address of 127.0.0.1. And at that point, the component now believes that I am online; why? because the 127.0.0.1 address does not exist in the interface IP address list. So for me, the component states exactly the OPPOSITE from my actual state.
Simply put, you are running into something that many of us have run in to. And that is, the difficulties involved with determining if a computer has network access to a remote destination (the internet). So, while there may be a number of different api calls, from a number of different libraries, only one thing is guaranteed: none of them can tell you 100%, without a doubt, that you are connected or not without actually attempting to reach the destination in question. As you have also found out, attempting to reach a destination when the communication channel is down can also be a lengthy process...(but one that could be resolved with the use of threads).
Regarding the conversion of the component (to a single line function); I considered it.... but have no plans on spending time converting something that does not work to start with.
Regards,
Russell
Maybe this would work (if it can be done).
Determine all installed hardware that is able to connect beyond the computer itself.
These are Networkcards and Modems (maybe Firewire 1394 and others?)
I assume that it is possible to gather all IP-addresses related to these hardware components.
Make a internal list of these IP's.
Check all IP's that are currently accessable.
If one of them isn't in the list of local IP's then I presume a connection is available with the internet (beyond the own local netwerk).
Regards, Stef
Stef,
What you describe above is not only difficult to achieve, but it also follows the same flawed logic as the component code you posted. It can only tell you about the next hop in your network configuration. For a computer connected to a local LAN system, then this will either be the router or dhcp server. It tells you absolutely nothing about your connection (or lack of) to an external network.
Anyways, I would like to finish this question up, and also have you satisfied with the results. You, on the same hand, should be willing to accept a small (3-5) second delay in the checking of the network when the internet connection is disabled or not connected.
So, in order to achieve this, I will work on converting some code over that performs icmp pinging. This should provide the results you are after, is very realiable, and can be set to timeout at a user defined time interval. While I am doing this, I wonder if you could check the following:
Replace the "www.google.com" param from the IsDestinationReachable(...
Regards,
Russell
Thought I was going to have to convert some C code over, but was pleasantly suprised to find that Franois had already translated the icmp code over to delphi.
Hopefull, this should work as well for you as it did for me....
function IsInternetConnected(Timeou
var icmpTest: TICMP;
begin
// Create icmp wrapper
icmpTest:=TICMP.Create;
// Resource protection
try
// Set timeout and destination address. This could also be enhanced as mentioned by Ivanov_g where
// you send out one request to multiple destinations, and just check to make sure that at least one replied.
// This would help to avoid the rare situautions when a site was down/unreachable, but you are connected.
icmpTest.Address:='64.233.
icmpTest.Timeout:=Timeout;
// Ping the destination
result:=(icmpTest.Ping > 0);
finally
// Free object
icmpTest.Free;
end;
end;
// To test the code - I used 1 second which is a pretty safe value.
if IsInternetConnected(1000) then
ShowMessage('Connected...'
else
ShowMessage('Not connected...');
Russell
-----
And the icmp code:
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Author: Franois PIETTE
Description: This unit encapsulate the ICMP.DLL into an object of type TICMP.
Using this object, you can easily ping any host on your network.
Works only in 32 bits mode (no Delphi 1) under NT or 95.
TICMP is perfect for a console mode program, but if you build a
GUI program, you could use the TPing object wich is a true VCL
encapsulating the TICMP object. Then you can use object inspector
to change properties or event handler. This is much simpler to
use for a GUI program.
EMail: http://users.swing.be/fran
http://www.rtfm.be/fpiette
francois.piette@pophost.eu
Creation: January 6, 1997
Version: 1.04
Support: Use the mailing list twsocket@rtfm.be See website for details.
Legal issues: Copyright (C) 1997-2000 by Franois PIETTE
Rue de Grady 24, 4053 Embourg, Belgium. Fax: +32-4-365.74.56
<francois.piette@pophost.e
This software is provided 'as-is', without any express or
implied warranty. In no event will the author be held liable
for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it
and redistribute it freely, subject to the following
restrictions:
1. The origin of this software must not be misrepresented,
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but is
not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
4. You must register this software by sending a picture postcard
to the author. Use a nice stamp and mention your name, street
address, EMail address and any comment you like to say.
Updates:
Dec 13, 1997 V1.01 Added OnEchoRequest and OnEchoReply events and removed the
corresponding OnDisplay event. This require to modify existing
programs.
Mar 15, 1998 V1.02 Deplaced address resolution just before use
Sep 24, 1998 V1.93 Changed TIPAddr and others to LongInt to avoid range error
problems with Delphi 4
Jan 24, 1999 V1.11 Surfaced Flags property to allow fragmentation check
(Flags = IP_FLAG_DF to enable fragmentation check)
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
unit Icmp;
interface
{$IFDEF VER80}
// This source file is *NOT* compatible with Delphi 1 because it uses
// Win 32 features.
{$ENDIF}
uses
Windows, SysUtils, Classes, WinSock;
const
IcmpVersion = 102;
IcmpDLL = 'icmp.dll';
// IP status codes returned to transports and user IOCTLs.
IP_SUCCESS = 0;
IP_STATUS_BASE = 11000;
IP_BUF_TOO_SMALL = (IP_STATUS_BASE + 1);
IP_DEST_NET_UNREACHABLE = (IP_STATUS_BASE + 2);
IP_DEST_HOST_UNREACHABLE = (IP_STATUS_BASE + 3);
IP_DEST_PROT_UNREACHABLE = (IP_STATUS_BASE + 4);
IP_DEST_PORT_UNREACHABLE = (IP_STATUS_BASE + 5);
IP_NO_RESOURCES = (IP_STATUS_BASE + 6);
IP_BAD_OPTION = (IP_STATUS_BASE + 7);
IP_HW_ERROR = (IP_STATUS_BASE + 8);
IP_PACKET_TOO_BIG = (IP_STATUS_BASE + 9);
IP_REQ_TIMED_OUT = (IP_STATUS_BASE + 10);
IP_BAD_REQ = (IP_STATUS_BASE + 11);
IP_BAD_ROUTE = (IP_STATUS_BASE + 12);
IP_TTL_EXPIRED_TRANSIT = (IP_STATUS_BASE + 13);
IP_TTL_EXPIRED_REASSEM = (IP_STATUS_BASE + 14);
IP_PARAM_PROBLEM = (IP_STATUS_BASE + 15);
IP_SOURCE_QUENCH = (IP_STATUS_BASE + 16);
IP_OPTION_TOO_BIG = (IP_STATUS_BASE + 17);
IP_BAD_DESTINATION = (IP_STATUS_BASE + 18);
// status codes passed up on status indications.
IP_ADDR_DELETED = (IP_STATUS_BASE + 19);
IP_SPEC_MTU_CHANGE = (IP_STATUS_BASE + 20);
IP_MTU_CHANGE = (IP_STATUS_BASE + 21);
IP_GENERAL_FAILURE = (IP_STATUS_BASE + 50);
MAX_IP_STATUS = IP_GENERAL_FAILURE;
IP_PENDING = (IP_STATUS_BASE + 255);
// IP header flags
IP_FLAG_DF = $02; // Don't fragment this packet.
// IP Option Types
IP_OPT_EOL = $00; // End of list option
IP_OPT_NOP = $01; // No operation
IP_OPT_SECURITY = $82; // Security option.
IP_OPT_LSRR = $83; // Loose source route.
IP_OPT_SSRR = $89; // Strict source route.
IP_OPT_RR = $07; // Record route.
IP_OPT_TS = $44; // Timestamp.
IP_OPT_SID = $88; // Stream ID (obsolete)
MAX_OPT_SIZE = $40;
type
// IP types
TIPAddr = LongInt; // An IP address.
TIPMask = LongInt; // An IP subnet mask.
TIPStatus = LongInt; // Status code returned from IP APIs.
PIPOptionInformation = ^TIPOptionInformation;
TIPOptionInformation = packed record
TTL: Byte; // Time To Live (used for traceroute)
TOS: Byte; // Type Of Service (usually 0)
Flags: Byte; // IP header flags (usually 0)
OptionsSize: Byte; // Size of options data (usually 0, max 40)
OptionsData: PChar; // Options data buffer
end;
PIcmpEchoReply = ^TIcmpEchoReply;
TIcmpEchoReply = packed record
Address: TIPAddr; // Replying address
Status: DWord; // IP status value
RTT: DWord; // Round Trip Time in milliseconds
DataSize: Word; // Reply data size
Reserved: Word; // Reserved
Data: Pointer; // Pointer to reply data buffer
Options: TIPOptionInformation; // Reply options
end;
// IcmpCreateFile:
// Opens a handle on which ICMP Echo Requests can be issued.
// Arguments:
// None.
// Return Value:
// An open file handle or INVALID_HANDLE_VALUE. Extended error information
// is available by calling GetLastError().
TIcmpCreateFile = function: THandle; stdcall;
// IcmpCloseHandle:
// Closes a handle opened by ICMPOpenFile.
// Arguments:
// IcmpHandle - The handle to close.
// Return Value:
// TRUE if the handle was closed successfully, otherwise FALSE. Extended
// error information is available by calling GetLastError().
TIcmpCloseHandle = function(IcmpHandle: THandle): Boolean; stdcall;
// IcmpSendEcho:
// Sends an ICMP Echo request and returns one or more replies. The
// call returns when the timeout has expired or the reply buffer
// is filled.
// Arguments:
// IcmpHandle - An open handle returned by ICMPCreateFile.
// DestinationAddress - The destination of the echo request.
// RequestData - A buffer containing the data to send in the
// request.
// RequestSize - The number of bytes in the request data buffer.
// RequestOptions - Pointer to the IP header options for the request.
// May be NULL.
// ReplyBuffer - A buffer to hold any replies to the request.
// On return, the buffer will contain an array of
// ICMP_ECHO_REPLY structures followed by options
// and data. The buffer should be large enough to
// hold at least one ICMP_ECHO_REPLY structure
// and 8 bytes of data - this is the size of
// an ICMP error message.
// ReplySize - The size in bytes of the reply buffer.
// Timeout - The time in milliseconds to wait for replies.
// Return Value:
// Returns the number of replies received and stored in ReplyBuffer. If
// the return value is zero, extended error information is available
// via GetLastError().
TIcmpSendEcho = function(IcmpHandle: THandle;
DestinationAddress: TIPAddr;
RequestData: Pointer;
RequestSize: Word;
RequestOptions: PIPOptionInformation;
ReplyBuffer: Pointer;
ReplySize: DWord;
Timeout: DWord
): DWord; stdcall;
// Event handler type declaration for TICMP.OnDisplay event.
TICMPDisplay = procedure(Sender: TObject; Msg : String) of object;
TICMPReply = procedure(Sender: TObject; Error : Integer) of object;
// The object wich encapsulate the ICMP.DLL
TICMP = class(TObject)
private
hICMPdll : HModule; // Handle for ICMP.DLL
IcmpCreateFile : TIcmpCreateFile;
IcmpCloseHandle : TIcmpCloseHandle;
IcmpSendEcho : TIcmpSendEcho;
hICMP : THandle; // Handle for the ICMP Calls
FReply : TIcmpEchoReply; // ICMP Echo reply buffer
FAddress : String; // Address given
FHostName : String; // Dotted IP of host (output)
FHostIP : String; // Name of host (Output)
FIPAddress : TIPAddr; // Address of host to contact
FSize : Integer; // Packet size (default to 56)
FTimeOut : Integer; // Timeout (default to 4000mS)
FTTL : Integer; // Time To Live (for send)
FFlags : Integer; // Options flags
FOnDisplay : TICMPDisplay; // Event handler to display
FOnEchoRequest : TNotifyEvent;
FOnEchoReply : TICMPReply;
FLastError : DWORD; // After sending ICMP packet
FAddrResolved : Boolean;
procedure ResolveAddr;
public
constructor Create; virtual;
destructor Destroy; override;
function Ping : Integer;
procedure SetAddress(Value : String);
function GetErrorString : String;
property Address : String read FAddress write SetAddress;
property Size : Integer read FSize write FSize;
property Timeout : Integer read FTimeout write FTimeout;
property Reply : TIcmpEchoReply read FReply;
property TTL : Integer read FTTL write FTTL;
Property Flags : Integer read FFlags write FFlags;
property ErrorCode : DWORD read FLastError;
property ErrorString : String read GetErrorString;
property HostName : String read FHostName;
property HostIP : String read FHostIP;
property OnDisplay : TICMPDisplay read FOnDisplay write FOnDisplay;
property OnEchoRequest : TNotifyEvent read FOnEchoRequest
write FOnEchoRequest;
property OnEchoReply : TICMPReply read FOnEchoReply
write FOnEchoReply;
end;
TICMPException = class(Exception);
implementation
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
constructor TICMP.Create;
var
WSAData: TWSAData;
begin
hICMP := INVALID_HANDLE_VALUE;
FSize := 56;
FTTL := 64;
FTimeOut := 4000;
// initialise winsock
if WSAStartup($101, WSAData) <> 0 then
raise TICMPException.Create('Err
// register the icmp.dll stuff
hICMPdll := LoadLibrary(icmpDLL);
if hICMPdll = 0 then
raise TICMPException.Create('Una
@ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile');
@IcmpCloseHandle := GetProcAddress(hICMPdll, 'IcmpCloseHandle');
@IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho');
if (@ICMPCreateFile = Nil) or
(@IcmpCloseHandle = Nil) or
(@IcmpSendEcho = Nil) then
raise TICMPException.Create('Err
hICMP := IcmpCreateFile;
if hICMP = INVALID_HANDLE_VALUE then
raise TICMPException.Create('Una
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
destructor TICMP.Destroy;
begin
if hICMP <> INVALID_HANDLE_VALUE then
IcmpCloseHandle(hICMP);
if hICMPdll <> 0 then
FreeLibrary(hICMPdll);
WSACleanup;
inherited Destroy;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function MinInteger(X, Y: Integer): Integer;
begin
if X >= Y then
Result := Y
else
Result := X;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TICMP.ResolveAddr;
var
Phe : PHostEnt; // HostEntry buffer for name lookup
begin
// Convert host address to IP address
FIPAddress := inet_addr(PChar(FAddress))
if FIPAddress <> LongInt(INADDR_NONE) then
// Was a numeric dotted address let it in this format
FHostName := FAddress
else begin
// Not a numeric dotted address, try to resolve by name
Phe := GetHostByName(PChar(FAddre
if Phe = nil then begin
FLastError := GetLastError;
if Assigned(FOnDisplay) then
FOnDisplay(Self, 'Unable to resolve ' + FAddress);
Exit;
end;
FIPAddress := longint(plongint(Phe^.h_ad
FHostName := Phe^.h_name;
end;
FHostIP := StrPas(inet_ntoa(TInAddr(F
FAddrResolved := TRUE;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
procedure TICMP.SetAddress(Value : String);
begin
// Only change if needed (could take a long time)
if FAddress = Value then
Exit;
FAddress := Value;
FAddrResolved := FALSE;
// ResolveAddr;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TICMP.GetErrorString : String;
begin
case FLastError of
IP_SUCCESS: Result := 'No error';
IP_BUF_TOO_SMALL: Result := 'Buffer too small';
IP_DEST_NET_UNREACHABLE: Result := 'Destination network unreachable';
IP_DEST_HOST_UNREACHABLE: Result := 'Destination host unreachable';
IP_DEST_PROT_UNREACHABLE: Result := 'Destination protocol unreachable';
IP_DEST_PORT_UNREACHABLE: Result := 'Destination port unreachable';
IP_NO_RESOURCES: Result := 'No resources';
IP_BAD_OPTION: Result := 'Bad option';
IP_HW_ERROR: Result := 'Hardware error';
IP_PACKET_TOO_BIG: Result := 'Packet too big';
IP_REQ_TIMED_OUT: Result := 'Request timed out';
IP_BAD_REQ: Result := 'Bad request';
IP_BAD_ROUTE: Result := 'Bad route';
IP_TTL_EXPIRED_TRANSIT: Result := 'TTL expired in transit';
IP_TTL_EXPIRED_REASSEM: Result := 'TTL expired in reassembly';
IP_PARAM_PROBLEM: Result := 'Parameter problem';
IP_SOURCE_QUENCH: Result := 'Source quench';
IP_OPTION_TOO_BIG: Result := 'Option too big';
IP_BAD_DESTINATION: Result := 'Bad Destination';
IP_ADDR_DELETED: Result := 'Address deleted';
IP_SPEC_MTU_CHANGE: Result := 'Spec MTU change';
IP_MTU_CHANGE: Result := 'MTU change';
IP_GENERAL_FAILURE: Result := 'General failure';
IP_PENDING: Result := 'Pending';
else
Result := 'ICMP error #' + IntToStr(FLastError);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
function TICMP.Ping : Integer;
var
BufferSize: Integer;
pReqData, pData: Pointer;
pIPE: PIcmpEchoReply; // ICMP Echo reply buffer
IPOpt: TIPOptionInformation; // IP Options for packet to send
Msg: String;
begin
Result := 0;
FLastError := 0;
if not FAddrResolved then
ResolveAddr;
if FIPAddress = LongInt(INADDR_NONE) then begin
FLastError := IP_BAD_DESTINATION;
if Assigned(FOnDisplay) then
FOnDisplay(Self, 'Invalid host address');
Exit;
end;
// Allocate space for data buffer space
BufferSize := SizeOf(TICMPEchoReply) + FSize;
GetMem(pReqData, FSize);
GetMem(pData, FSize);
GetMem(pIPE, BufferSize);
try
// Fill data buffer with some data bytes
FillChar(pReqData^, FSize, $20);
Msg := 'Pinging from Delphi code written by F. Piette';
Move(Msg[1], pReqData^, MinInteger(FSize, Length(Msg)));
pIPE^.Data := pData;
FillChar(pIPE^, SizeOf(pIPE^), 0);
if Assigned(FOnEchoRequest) then
FOnEchoRequest(Self);
FillChar(IPOpt, SizeOf(IPOpt), 0);
IPOpt.TTL := FTTL;
IPOpt.Flags := FFlags;
Result := IcmpSendEcho(hICMP, FIPAddress, pReqData, FSize,
@IPOpt, pIPE, BufferSize, FTimeOut);
FLastError := GetLastError;
FReply := pIPE^;
if Assigned(FOnEchoReply) then
FOnEchoReply(Self, Result);
finally
// Free those buffers
FreeMem(pIPE);
FreeMem(pData);
FreeMem(pReqData);
end;
end;
{* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *}
end.
Business Accounts
Answer for Membership
by: Ivanov_GPosted on 2004-12-12 at 12:40:42ID: 12805078
try to ping some address in internet, or better your ISP servers (gateway or DNS) since it will be much faster. Send 3 pings and if 1 returns - you are online :)