Ping a computer using TCP stacks

.

This class addresses a common problem: how to ping a computer from a Win95
machine using the MS-TCP stacks. This will also work for NT 3.51 and 4.0.
To make the problem more complex, MS did not include a mechanism for doing
this in it’s Winsock implementation.

The way around the problem is in using the ICMP DLL. This workaround is
highly discouraged by Microsoft, but until Winsock 2.0, there was no other
way to do a simple ping.

The problem: given a computer name, or given an IP address, ping the computer
and return the ping response time. This requires access to the ICMP DLL, and
to some of the socket structures provided in CSocket. Also, the class is
derived from CSocket for future extension purposes.

Please note that to run this you’ll need to get the ICMPAPI.H,
ICMP.LIB, and IPEXPORT.H files from Microsoft, and place the lib and
include files in your build settings. They are available on the
Microsoft Developers Network CD’s, and I believe on the Microsoft Web
site as well.

The class includes four public functions:

unsigned long ResolveIP(CString strIP)
unsigned long ResolveName(CString strHostName)
CString GetIP(unsigned long ulIP)
DWORD PingHost(unsigned long ulIP, int iPingTimeout)

ResolveIP takes a CString IP address (i.e. “123.123.123.123”), and returns
it’s byte-ordered network address.

ResolveName takes a CString host name (i.e. ComputerName), resolves the
name through DNS or WINS, and then returns the byte-ordered network address.
Note that this uses a blocking GetHostByName.

GetIP takes the byte-ordered network address, and returns the IP address as
a CString (i.e. “123.123.123.123”).

PingHost takes the byte-ordered network address, a timeout integer, pings
the address, and returns the ping response time.

/*
//------------------------------------------------------------------------------------------------------------------
//icmpecho.h
//------------------------------------------------------------------------------------------------------------------
*
class CIcmpEcho : public CSocket
{
// Attributes
public:

// Operations
public:
	CIcmpEcho();
	virtual ~CIcmpEcho();

	unsigned long ResolveIP(CString strIP);
	unsigned long ResolveName(CString strHostName);

	DWORD PingHost(unsigned long ulIP, int iPingTimeout);

	CString GetIP(unsigned long ulIP);

// Overrides
public:
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CIcmpEcho)
	//}}AFX_VIRTUAL

	// Generated message map functions
	//{{AFX_MSG(CIcmpEcho)
		// NOTE - the ClassWizard will add and remove member functions here.
	//}}AFX_MSG

// Implementation
protected:
};
/////////////////////////////////////////////////////////////////////////////







/*
//------------------------------------------------------------------------------------------------------------------
//icmpecho.cpp
//------------------------------------------------------------------------------------------------------------------
*
// IcmpEcho.cpp : implementation file
//

#include "IcmpEcho.h"

extern "C" {
#include "ipexport.h"
#include "icmpapi.h"
}

#define PING_TIMEOUT 100

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CIcmpEcho

CIcmpEcho::CIcmpEcho()
{
}

CIcmpEcho::~CIcmpEcho()
{
}


// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CIcmpEcho, CSocket)
	//{{AFX_MSG_MAP(CIcmpEcho)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif	// 0

/////////////////////////////////////////////////////////////////////////////
// CIcmpEcho member functions
unsigned long CIcmpEcho::ResolveIP(CString strIP)
{
	//Task 1:	Given IP Address i.e. "111.111.111.111",
	//	Return Network byte ordered address (ulIP)

	unsigned long ulIP;

	ulIP =(IPAddr)inet_addr(strIP);

	return ulIP;
}

unsigned long CIcmpEcho::ResolveName(CString strHostName)
{
	//Task 1:	Resolve HostName (through DNS or WINS, whichever appropriate)
	//Task 2:	Return network byte ordered address (ulIP)

	unsigned long ulIP;
	hostent* phostent;

	phostent = gethostbyname(strHostName);

	if (phostent == NULL)
		return 0;

	ulIP = *(DWORD*)(*phostent->h_addr_list);

	return ulIP;

}

DWORD CIcmpEcho::PingHost(unsigned long ulIP, int iPingTimeout)
{
	//Task 1:	Open ICMP Handle
	//Task 2:	Create Structure to receive ping reply
	//Task 3:	SendPing (SendEcho)
	//Task 4:	Close ICMP Handle
	//Task 5:	Return RoundTripTime

	unsigned long ip = ulIP;

	HANDLE icmphandle = IcmpCreateFile();

	char reply[sizeof(icmp_echo_reply)+8];

	icmp_echo_reply* iep=(icmp_echo_reply*)&reply;
	iep->RoundTripTime = 0xffffffff;

	IcmpSendEcho(icmphandle,ip,0,0,NULL,reply,sizeof(icmp_echo_reply)+8,iPingTimeout);

	IcmpCloseHandle(icmphandle);

	return iep->RoundTripTime;

}

CString CIcmpEcho::GetIP(unsigned long ulIP)
{
	//Task 1:	Given a host order ulIP Address
	//	Return a IP address in format of xxx.xxx.xxx.xxx

	LPSTR szAddr;

	struct in_addr inetAddr;

	inetAddr.s_addr = (IPAddr)ulIP;

	szAddr = inet_ntoa(inetAddr);

	CString csIP = szAddr;

	return csIP;

}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read