#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;