Pingip.cpp
#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;//pingfor (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_shortu = 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回應的請求和回答函數intSendEchoRequest(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 IHLu_charTOS; //Type Of ServiceshortTotLen; //總長度shortID; //標識shortFlagOff; //標記u_charTTL; //生命期u_charProtocol; //協議u_shortChecksum; //檢查和structin_addr iaSrc; //源地址structin_addr iaDst; //目的地址}IPHDR, *PIPHDR;typedef struct IC_MPHDR{u_charType; //類型u_charCode; //編碼u_shortChecksum; //檢查和u_shortID; //標識u_shortSeq; //順序charData; //資料}ICMPHDR, *PICMPHDR;typedef struct ICMPECHOREQUEST{ICMPHDR icmpHdr;DWORDdwTime;charcData[REQ_DATASIZE];}ECHOREQUEST, *PECHOREQUEST;typedef struct ICMPECHOREPLY{IPHDRiphdr;ECHOREQUESTechorequest;char cFiller[256];}ECHOREPLY, *PECHOREPLY;