头文件
#pragma once
#include <Winsock2.h>
#include <IPHlpApi.h>
#pragma comment(lib, "Iphlpapi.lib")
#pragma comment(lib, "Ws2_32.lib")
typedef HANDLE(WINAPI* ICMPCREATEFILE)(VOID);
typedef INT(WINAPI* ICMPCLOSEHANDLE)(HANDLE);
typedef DWORD(WINAPI* ICMPSENDECHO)(HANDLE, DWORD, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD);
class CICMPPing
{
public:
CICMPPing(void);
~CICMPPing(void);
BOOL InitializeICMP();
BOOL Ping(const char* host);
VOID ReleaseICMP();
private:
HINSTANCE m_hDLL;
ICMPCREATEFILE m_pIcmpCreateFile;
ICMPCLOSEHANDLE m_pIcmpCloseHandle;
ICMPSENDECHO m_pIcmpSendEcho;
};
CPP文件
#include "StdAfx.h"
#include "ICMPPing.h"
CICMPPing::CICMPPing(void)
{
m_hDLL = NULL;
m_pIcmpSendEcho = NULL;
m_pIcmpCreateFile = NULL;
m_pIcmpCloseHandle = NULL;
}
CICMPPing::~CICMPPing(void)
{
ReleaseICMP();
}
BOOL CICMPPing::InitializeICMP()
{
m_hDLL = ::LoadLibrary(_T("ICMP.DLL"));
if (NULL != m_hDLL)
{
m_pIcmpCreateFile = (ICMPCREATEFILE)GetProcAddress(m_hDLL, "IcmpCreateFile");
m_pIcmpCloseHandle = (ICMPCLOSEHANDLE)GetProcAddress(m_hDLL, "IcmpCloseHandle");
m_pIcmpSendEcho = (ICMPSENDECHO)GetProcAddress(m_hDLL, "IcmpSendEcho");
if ((m_pIcmpCreateFile == NULL) || (m_pIcmpCloseHandle == NULL) || (m_pIcmpSendEcho == NULL))
return FALSE;
return TRUE;
}
return FALSE;
}
BOOL CICMPPing::Ping(const char* host)
{
DWORD timeOut = 500; //设置超时
ULONG hAddr = inet_addr(host); //如果是IP地址就直接转换
if (hAddr == INADDR_NONE)
{
hostent* hp = gethostbyname(host); //如果是域名就用DNS解析出IP地址
if (hp)
memcpy(&hAddr, hp->h_addr_list, hp->h_length); //IP地址
else
{
return FALSE;
}
}
HANDLE hIp = m_pIcmpCreateFile();
IP_OPTION_INFORMATION ipoi;
memset(&ipoi, 0, sizeof(IP_OPTION_INFORMATION));
ipoi.Ttl = 128; //Time-To-Live
unsigned char pSend[36] = {0}; //发送包
memset(pSend, 'E', 32);
int repSize = sizeof(ICMP_ECHO_REPLY) + 32;
unsigned char pReply[100]; //接收包
ICMP_ECHO_REPLY* pEchoReply = (ICMP_ECHO_REPLY*)pReply;
DWORD nPackets = m_pIcmpSendEcho(hIp, hAddr, pSend, 32, &ipoi, pReply, repSize, timeOut); //发送ICMP数据报文
if (pEchoReply->Status != 0) //超时,可能是主机禁用了ICMP 或者目标主机不存在
{
m_pIcmpCloseHandle(hIp);
return FALSE;
}
m_pIcmpCloseHandle(hIp);
return TRUE;
}
VOID CICMPPing::ReleaseICMP()
{
if (NULL != m_hDLL)
{
::FreeLibrary(m_hDLL);
m_pIcmpCloseHandle = NULL;
m_pIcmpCreateFile = NULL;
m_pIcmpSendEcho = NULL;
}
}