网上找的两个pingIP地址的类A和B
A.h
#include <IPHlpApi.h>
#pragma comment(lib, "iphlpapi.lib")
class CPing
{
public:
CPing(void);
~CPing(void);
private:
HINSTANCE hIcmp;
typedef HANDLE(WINAPI *PIcmpCreateFile)(VOID);
typedef DWORD(WINAPI *PIcmpSendEcho)(HANDLE, IPAddr, LPVOID, WORD, PIP_OPTION_INFORMATION, LPVOID, DWORD, DWORD);
typedef BOOL(WINAPI *PIcmpCloseHandle)(HANDLE);
PIcmpCreateFile pIcmpCreateFile;
PIcmpSendEcho pIcmpSendEcho;
PIcmpCloseHandle pIcmpCloseHandle;
public:
//功能:ping某个地址或者Ip,返回结果
//参数:v_pszDesAddress-目标域名或者IP
//参数:v_usTimes-需要ping的次数
//参数:v_ulTimeout-超时时间,单位毫秒
//返回值:-1-发生异常,其他大于等于0的值表示未超时的次数
int Ping(const char *v_pszDesAdress, USHORT v_usTimes, ULONG v_ulTimeout);
};
A.cpp
#include "StdAfx.h"
#include ".\ping.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
//构造函数
CPing::CPing(void)
{
hIcmp = LoadLibrary("icmp.dll");
if (NULL != hIcmp)
{
pIcmpCreateFile = (PIcmpCreateFile)GetProcAddress(hIcmp, "IcmpCreateFile");
pIcmpSendEcho = (PIcmpSendEcho)GetProcAddress(hIcmp, "IcmpSendEcho");
pIcmpCloseHandle = (PIcmpCloseHandle)GetProcAddress(hIcmp, "IcmpCloseHandle");
}
}
//析构函数
CPing::~CPing(void)
{
FreeLibrary(hIcmp);
}
//功能:ping某个地址或者Ip,返回结果
//参数:v_pszDesAddress-目标域名或者IP
//参数:v_usTimes-需要ping的次数
//参数:v_ulTimeout-超时时间,单位毫秒
//返回值:-1-发生异常,其他大于等于0的值表示未超时的次数
int CPing::Ping(const char *v_pszDesAdress, USHORT v_usTimes, ULONG v_ulTimeout)
{
ULONG ulDesIP = 0;
int ret = 0;
// 当传递的参数为域名时,解析该域名的IP
ulDesIP = inet_addr(v_pszDesAdress);
//域名
if (ulDesIP == INADDR_NONE)
{
// 解析传入域名的IP
PHOSTENT pHostent = gethostbyname(v_pszDesAdress);
if (pHostent == NULL)
{
return -1;
}
ulDesIP = *(DWORD *)pHostent->h_addr;
}
// 申请发送缓冲区
void *sendBuffer = new char[32];
if (sendBuffer == NULL)
{
return -1;
}
// 申请接收缓冲区
unsigned long replySize = sizeof(ICMP_ECHO_REPLY)+32;
void *replyBuffer = new char[replySize];
if (replyBuffer == NULL)
{
delete[] sendBuffer;
sendBuffer = NULL;
return -1;
}
PICMP_ECHO_REPLY pIcmpEchoReply = (PICMP_ECHO_REPLY)replyBuffer;
// 获取ICMP echo所需句柄
HANDLE hIcmpFile = pIcmpCreateFile();
if (hIcmpFile == INVALID_HANDLE_VALUE)
{
delete[] sendBuffer;
sendBuffer = NULL;
delete[] replyBuffer;
replyBuffer = NULL;
return -1;
}
// 调用IcmpSendEcho,获取Ping值
for (int i = 0; i<v_usTimes; i++)
{
pIcmpSendEcho(hIcmpFile, ulDesIP, sendBuffer, 32, NULL, replyBuffer, replySize, v_ulTimeout);
if (pIcmpEchoReply->Status == 0) // 未超时
{
ret++;
}
}
//释放缓冲区,关闭句柄
delete[] replyBuffer;
delete[] sendBuffer;
pIcmpCloseHandle(hIcmpFile);
return ret;
}
B.h
#pragma once
//这里需要导入库 Ws2_32.lib,在不同的IDE下可能不太一样
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define DEF_PACKET_SIZE 32
#define ECHO_REQUEST 8
#define ECHO_REPLY 0
struct IPHeader
{
BYTE m_byVerHLen; //4位版本+4位首部长度
BYTE m_byTOS; //服务类型
USHORT m_usTotalLen; //总长度
USHORT m_usID; //标识
USHORT m_usFlagFragOffset; //3位标志+13位片偏移
BYTE m_byTTL; //TTL
BYTE m_byProtocol; //协议
USHORT m_usHChecksum; //首部检验和
ULONG m_ulSrcIP; //源IP地址
ULONG m_ulDestIP; //目的IP地址
};
struct ICMPHeader
{
BYTE m_byType; //类型
BYTE m_byCode; //代码
USHORT m_usChecksum; //检验和
USHORT m_usID; //标识符
USHORT m_usSeq; //序号
ULONG m_ulTimeStamp; //时间戳(非标准ICMP头部)
};
struct PingReply
{
USHORT m_usSeq;
DWORD m_dwRoundTripTime;
DWORD m_dwBytes;
DWORD m_dwTTL;
};
class CPing
{
public:
CPing();
~CPing();
BOOL Ping(DWORD dwDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);
BOOL Ping(char *szDestIP, PingReply *pPingReply = NULL, DWORD dwTimeout = 2000);
private:
BOOL PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout);
USHORT CalCheckSum(USHORT *pBuffer, int nSize);
ULONG GetTickCountCalibrate();
private:
SOCKET m_sockRaw;
WSAEVENT m_event;
USHORT m_usCurrentProcID;
char *m_szICMPData;
BOOL m_bIsInitSucc;
private:
static USHORT s_usPacketSeq;
};
B.cpp
#include "stdafx.h"
#include "Ping.h"
USHORT CPing::s_usPacketSeq = 0;
CPing::CPing() :
m_szICMPData(NULL),
m_bIsInitSucc(FALSE)
{
WSADATA WSAData;
WSAStartup(MAKEWORD(1, 1), &WSAData);
m_event = WSACreateEvent();
m_usCurrentProcID = (USHORT)GetCurrentProcessId();
if ((m_sockRaw = WSASocket(AF_INET, SOCK_RAW, IPPROTO_ICMP, NULL, 0, 0)) != SOCKET_ERROR)
{
WSAEventSelect(m_sockRaw, m_event, FD_READ);
m_bIsInitSucc = TRUE;
int sz = DEF_PACKET_SIZE + sizeof(ICMPHeader);
m_szICMPData = new char[sz];
memset(m_szICMPData, 0, sz);
if (m_szICMPData == NULL)
{
m_bIsInitSucc = FALSE;
}
}
}
CPing::~CPing()
{
WSACleanup();
if (NULL != m_szICMPData)
{
delete[]m_szICMPData;
m_szICMPData = NULL;
}
}
BOOL CPing::Ping(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
return PingCore(dwDestIP, pPingReply, dwTimeout);
}
BOOL CPing::Ping(char *szDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
if (NULL != szDestIP)
{
return PingCore(inet_addr(szDestIP), pPingReply, dwTimeout);
}
return FALSE;
}
BOOL CPing::PingCore(DWORD dwDestIP, PingReply *pPingReply, DWORD dwTimeout)
{
//判断初始化是否成功
if (!m_bIsInitSucc)
{
return FALSE;
}
//配置SOCKET
sockaddr_in sockaddrDest;
sockaddrDest.sin_family = AF_INET;
sockaddrDest.sin_addr.s_addr = dwDestIP;
int nSockaddrDestSize = sizeof(sockaddrDest);
//构建ICMP包
int nICMPDataSize = DEF_PACKET_SIZE + sizeof(ICMPHeader);
ULONG ulSendTimestamp = GetTickCountCalibrate();
USHORT usSeq = ++s_usPacketSeq;
memset(m_szICMPData, 0, nICMPDataSize);
ICMPHeader *pICMPHeader = (ICMPHeader*)m_szICMPData;
pICMPHeader->m_byType = ECHO_REQUEST;
pICMPHeader->m_byCode = 0;
pICMPHeader->m_usID = m_usCurrentProcID;
pICMPHeader->m_usSeq = usSeq;
pICMPHeader->m_ulTimeStamp = ulSendTimestamp;
pICMPHeader->m_usChecksum = CalCheckSum((USHORT*)m_szICMPData, nICMPDataSize);
//发送ICMP报文
if (sendto(m_sockRaw, m_szICMPData, nICMPDataSize, 0, (struct sockaddr*)&sockaddrDest, nSockaddrDestSize) == SOCKET_ERROR)
{
return FALSE;
}
//判断是否需要接收相应报文
if (pPingReply == NULL)
{
return TRUE;
}
char recvbuf[256] = { "\0" };
while (TRUE)
{
//接收响应报文
if (WSAWaitForMultipleEvents(1, &m_event, FALSE, 100, FALSE) != WSA_WAIT_TIMEOUT)
{
WSANETWORKEVENTS netEvent;
WSAEnumNetworkEvents(m_sockRaw, m_event, &netEvent);
if (netEvent.lNetworkEvents & FD_READ)
{
ULONG nRecvTimestamp = GetTickCountCalibrate();
int nPacketSize = recvfrom(m_sockRaw, recvbuf, 256, 0, (struct sockaddr*)&sockaddrDest, &nSockaddrDestSize);
if (nPacketSize != SOCKET_ERROR)
{
IPHeader *pIPHeader = (IPHeader*)recvbuf;
USHORT usIPHeaderLen = (USHORT)((pIPHeader->m_byVerHLen & 0x0f) * 4);
ICMPHeader *pICMPHeader = (ICMPHeader*)(recvbuf + usIPHeaderLen);
if (pICMPHeader->m_usID == m_usCurrentProcID //是当前进程发出的报文
&& pICMPHeader->m_byType == ECHO_REPLY //是ICMP响应报文
&& pICMPHeader->m_usSeq == usSeq //是本次请求报文的响应报文
)
{
pPingReply->m_usSeq = usSeq;
pPingReply->m_dwRoundTripTime = nRecvTimestamp - pICMPHeader->m_ulTimeStamp;
pPingReply->m_dwBytes = nPacketSize - usIPHeaderLen - sizeof(ICMPHeader);
pPingReply->m_dwTTL = pIPHeader->m_byTTL;
return TRUE;
}
}
}
}
//超时
if (GetTickCountCalibrate() - ulSendTimestamp >= dwTimeout)
{
return FALSE;
}
}
}
USHORT CPing::CalCheckSum(USHORT *pBuffer, int nSize)
{
unsigned long ulCheckSum = 0;
while (nSize > 1)
{
ulCheckSum += *pBuffer++;
nSize -= sizeof(USHORT);
}
if (nSize)
{
ulCheckSum += *(UCHAR*)pBuffer;
}
ulCheckSum = (ulCheckSum >> 16) + (ulCheckSum & 0xffff);
ulCheckSum += (ulCheckSum >> 16);
return (USHORT)(~ulCheckSum);
}
ULONG CPing::GetTickCountCalibrate()
{
static ULONG s_ulFirstCallTick = 0;
static LONGLONG s_ullFirstCallTickMS = 0;
SYSTEMTIME systemtime;
FILETIME filetime;
GetLocalTime(&systemtime);
SystemTimeToFileTime(&systemtime, &filetime);
LARGE_INTEGER liCurrentTime;
liCurrentTime.HighPart = filetime.dwHighDateTime;
liCurrentTime.LowPart = filetime.dwLowDateTime;
LONGLONG llCurrentTimeMS = liCurrentTime.QuadPart / 10000;
if (s_ulFirstCallTick == 0)
{
s_ulFirstCallTick = GetTickCount();
}
if (s_ullFirstCallTickMS == 0)
{
s_ullFirstCallTickMS = llCurrentTimeMS;
}
return s_ulFirstCallTick + (ULONG)(llCurrentTimeMS - s_ullFirstCallTickMS);
}
其中A类使用:
加上头文件
CPing Ping;
int su = 0;
su = Ping.Ping("www.baidu.com",4,1000);//域名或者IP地址,ping的次数,超时事件
判断su的值,如果为-1即为异常,0为没有ping同,4为ping通
B类使用:
头文件
CPing objPing;
PingReply reply;
memset(&reply, 0, sizeof reply);
//DWORD dwAddress = ntohl(inet_addr("195.6.4.52"));CString转换为DWORD
while (TRUE)
{
objPing.Ping("195.6.4.52", &reply);
if (reply.m_dwBytes == 0)
{
m_ping = false;//失败
MessageBox("失败");
break;
}
else//ping通了
{
m_ping = true;
MessageBox("成功");
}
}
这个类使用不是很方便,无法使用CString或者DWORD的IP地址来判断,只是使用简单的确定的ip地址来ping,