#include “stdafx.h”
#include “ping.h”
void CPing::Ping(UINT nRetries,LPCSTR pstrHost,HWND hWnd)
{
SOCKET rawSocket;
LPHOSTENT lpHost;
UINT nLoop;
int nRet;
struct sockaddr_in saDest;
struct sockaddr_in saSrc;
DWORD dwTimeSent;
DWORD dwElapsed;
u_char cTTL;
m_hWnd = hWnd;
CString str;
//创建一个Raw套接字
rawSocket = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
if (rawSocket == SOCKET_ERROR)
{
CString strMsg;
strMsg.Format(“创建套接字发生错误 – WSAError: %ld”,WSAGetLastError());
//发送报错信息
SendMessage(m_hWnd,WM_MSG_STATUS,0,(LPARAM) AllocBuffer(strMsg));
return;
}
//获得主机信息
lpHost = gethostbyname(pstrHost);
//构造目标套接字地址信息
saDest.sin_addr.s_addr = *((u_long FAR *)(lpHost->h_addr));
saDest.sin_family = AF_INET;
saDest.sin_port = 70;
//ping
for (nLoop = 0; nLoop < nRetries; nLoop++)
{
//发送ICMP回应请求
SendEchoRequest(rawSocket, &saDest);
nRet = WaitForEchoReply(rawSocket);
if (!nRet)
{
str.Format(“Request Timed Out”);
SendMessage(m_hWnd,WM_MSG_STATUS,3,(LPARAM)AllocBuffer(str));
}
else
{
//获得回应
dwTimeSent = RecvEchoReply(rawSocket,&saSrc,&cTTL);
//计算时间
dwElapsed = GetTickCount() – dwTimeSent;
str.Format(“Reply from: %s: bytes=%d time=%ldms TTL=%d”,
inet_ntoa(saSrc.sin_addr),REQ_DATASIZE,dwElapsed,cTTL);
SendMessage(m_hWnd,WM_MSG_STATUS,2,(LPARAM)AllocBuffer(str));
Sleep(1000);
}
}
nRet = closesocket(rawSocket);
if (nRet == SOCKET_ERROR)
{
CString strMsg;
strMsg.Format(“关闭套接字发生错误 – WSAError: %ld”,WSAGetLastError());
//发送报错信息
SendMessage(m_hWnd,WM_MSG_STATUS,0,(LPARAM) AllocBuffer(strMsg));
}
}
//发送ICMPECHO数据包请求
int CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)
{
static ECHOREQUEST echo;
static nId = 1;
static nSeq = 1;
int nRet;
//构造回应请求
echo.icmpHdr.Type = 8;
echo.icmpHdr.Code = 0;
echo.icmpHdr.Checksum = 0;
echo.icmpHdr.ID = nId++;
echo.icmpHdr.Seq = nSeq++;
for(nRet=0;nRet<REQ_DATASIZE;nRet++)
echo.cData[nRet] = ‘ ‘+nRet;
//保存发送时间
echo.dwTime = GetTickCount();
echo.icmpHdr.Checksum = in_cksum((u_short *)&echo,sizeof(ECHOREQUEST));
//发送请求
nRet = sendto(s,(LPSTR)&echo,sizeof(ECHOREQUEST),0,
(LPSOCKADDR)lpstToAddr,sizeof(SOCKADDR_IN));
if (nRet == SOCKET_ERROR)
{
CString strMsg;
strMsg.Format(“发送数据时发生错误 – WSAError: %ld”,WSAGetLastError());
//发送报错信息
SendMessage(m_hWnd,WM_MSG_STATUS,0,(LPARAM) AllocBuffer(strMsg));
}
return (nRet);
}
//接收ICMPECHO数据包回应
DWORD CPing::RecvEchoReply(SOCKET s,LPSOCKADDR_IN lpsaFrom,u_char *pTTL)
{
ECHOREPLY echoReply;
int nRet;
int nAddrLen = sizeof(struct sockaddr_in);
//接收请求回应
nRet = recvfrom(s,(LPSTR)&echoReply,sizeof(ECHOREPLY),0,
(LPSOCKADDR)lpsaFrom,&nAddrLen);
//检查返回值
if (nRet == SOCKET_ERROR)
{
CString strMsg;
strMsg.Format(“接收数据时发生错误 – WSAError: %ld”,WSAGetLastError());
//发送报错信息
SendMessage(m_hWnd,WM_MSG_STATUS,0,(LPARAM) AllocBuffer(strMsg));
}
//返回发送的时间
*pTTL = echoReply.iphdr.TTL;
return(echoReply.echorequest.dwTime);
}
//等待回应
int CPing::WaitForEchoReply(SOCKET s)
{
struct timeval Time;
fd_set fds;
fds.fd_count = 1;
fds.fd_array[0] = s;
Time.tv_sec = 1;
Time.tv_usec = 0;
return(select(1,&fds,NULL,NULL,&Time));
}
//转换地址
u_short CPing::in_cksum(u_short *addr,int len)
{
register int nleft = len;
register u_short *n = addr;
register u_short answer;
register int sum = 0;
while(nleft > 1)
{
sum += *n++;
nleft -= 2;
}
if(nleft == 1)
{
u_short u = 0;
*(u_char *)(&u) = *(u_char *)n;
sum += u;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer = ~sum;
return (answer);
}
char* CPing::AllocBuffer(CString strMsg)
{
int nLen = strMsg.GetLength();
char *pBuffer = new char[nLen+1];
strcpy(pBuffer,(const char*)strMsg);
ASSERT(pBuffer != NULL);
return pBuffer;
}
pingip.h
// Ping.h
//
#define REQ_DATASIZE 32 //Echo请求数据的大小
class CPing
{
public:
static char* AllocBuffer(CString strMsg);
HWND m_hWnd; //窗口句柄
void Ping(UINT nRetries,LPCSTR pstrHost,HWND hWnd);
int WaitForEchoReply(SOCKET s);
//ICMP回应的请求和回答函数
int SendEchoRequest(SOCKET, LPSOCKADDR_IN);
DWORD RecvEchoReply(SOCKET, LPSOCKADDR_IN,u_char *pTTL);
u_short in_cksum(u_short *addr, int len);
protected:
};
typedef struct IP_HDR
{
u_char VIHL; //Version and IHL
u_char TOS; //Type Of Service
short TotLen; //总长度
short ID; //标识
short FlagOff; //标记
u_char TTL; //生命期
u_char Protocol; //协议
u_short Checksum; //检查和
struct in_addr iaSrc; //源地址
struct in_addr iaDst; //目的地址
}IPHDR, *PIPHDR;
typedef struct IC_MPHDR
{
u_char Type; //类型
u_char Code; //编码
u_short Checksum; //检查和
u_short ID; //标识
u_short Seq; //顺序
char Data; //数据
}ICMPHDR, *PICMPHDR;
typedef struct ICMPECHOREQUEST
{
ICMPHDR icmpHdr;
DWORD dwTime;
char cData[REQ_DATASIZE];
}ECHOREQUEST, *PECHOREQUEST;
typedef struct ICMPECHOREPLY
{
IPHDR iphdr;
ECHOREQUEST echorequest;
char cFiller[256];
}ECHOREPLY, *PECHOREPLY;