#pragma once #include "StdAfx.h" #include "MyPingip.h" //#include //#pragma comment (lib , "Iphlpapi.lib") #pragma comment (lib , "wsock32.lib") #pragma warning(disable : 4996) #define WM_MSG_STATUS WM_USER + 100 CMyPingip::CMyPingip(void) { } CMyPingip::~CMyPingip(void) { } bool CMyPingip::PingFunction(LPCSTR pstrHost/*, Logger *pLog*/) { int nRetries = 5; int nLostConnectCnt = 0; bool bRet = true; WSADATA wsaData; WORD wVersionRequested; wVersionRequested = MAKEWORD( 2, 0 ); if(WSAStartup(wVersionRequested ,&wsaData) != 0) { return false; } SOCKET rawSocket; int nLoop; int nRet; struct sockaddr_in saDest; struct sockaddr_in saSrc; DWORD dwTimeSent; DWORD dwElapsed; u_char cTTL; //创建一个Raw套接字 rawSocket = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if (rawSocket == SOCKET_ERROR) { //PRINTA_INFO(pLog, "Create Socket Error – WSAError: %ld", WSAGetLastError()); return false; } //获得主机信息 //lpHost = gethostbyname(pstrHost); //构造目标套接字地址信息 saDest.sin_addr.s_addr = inet_addr(pstrHost)/**((u_long FAR *)(lpHost->h_addr))*/; saDest.sin_family = AF_INET; saDest.sin_port = 0; //ping for (nLoop = 0; nLoop < nRetries; nLoop++) { //发送ICMP回应请求 SendEchoRequest(rawSocket, &saDest); nRet = WaitForEchoReply(rawSocket); if (!nRet) //没有回应,不再一个IP段 { //PRINTA_INFO(pLog, "Request Timed Out"); nLostConnectCnt++; } else //在一个IP段,回应正确或者回应不可达 { dwTimeSent = RecvEchoReply(rawSocket,&saSrc,&cTTL); //获得回应 LPCSTR strIp = inet_ntoa(saSrc.sin_addr); if (strcmp(strIp,pstrHost)==0 ) { dwElapsed = GetTickCount()-dwTimeSent; //计算时间 //PRINTA_INFO(pLog, "Reply from: %s: bytes=%d time=%d ms TTL=%d", strIp, REQ_DATASIZE, dwElapsed, cTTL); } else { nLostConnectCnt++; //PRINTA_INFO(pLog, "Reply from: %s: Destination host unreachable", strIp); } } } nRet = closesocket(rawSocket); if (nRet == SOCKET_ERROR) { //PRINTA_INFO(pLog, "Close Socket Error – WSAError: %ld", WSAGetLastError()); } WSACleanup(); if (nLostConnectCnt>=3) { bRet = false; } return bRet; } //发送ICMPECHO数据包请求 int CMyPingip::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) { static ECHOREQUEST echo; static int nId = 1; static int 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 CMyPingip::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 CMyPingip::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 CMyPingip::in_cksum(u_short *addr,int len) { int nleft = len; u_short *n = addr; u_short answer; 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); }