MyPingip.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #pragma once
  2. #include "StdAfx.h"
  3. #include "MyPingip.h"
  4. //#include <iphlpapi.h>
  5. //#pragma comment (lib , "Iphlpapi.lib")
  6. #pragma comment (lib , "wsock32.lib")
  7. #pragma warning(disable : 4996)
  8. #define WM_MSG_STATUS WM_USER + 100
  9. CMyPingip::CMyPingip(void)
  10. {
  11. }
  12. CMyPingip::~CMyPingip(void)
  13. {
  14. }
  15. bool CMyPingip::PingFunction(LPCSTR pstrHost/*, Logger *pLog*/)
  16. {
  17. int nRetries = 5;
  18. int nLostConnectCnt = 0;
  19. bool bRet = true;
  20. WSADATA wsaData;
  21. WORD wVersionRequested;
  22. wVersionRequested = MAKEWORD( 2, 0 );
  23. if(WSAStartup(wVersionRequested ,&wsaData) != 0)
  24. {
  25. return false;
  26. }
  27. SOCKET rawSocket;
  28. LPHOSTENT lpHost;
  29. UINT nLoop;
  30. int nRet;
  31. struct sockaddr_in saDest;
  32. struct sockaddr_in saSrc;
  33. DWORD dwTimeSent;
  34. DWORD dwElapsed;
  35. u_char cTTL;
  36. //创建一个Raw套接字
  37. rawSocket = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
  38. if (rawSocket == SOCKET_ERROR)
  39. {
  40. //PRINTA_INFO(pLog, "Create Socket Error – WSAError: %ld", WSAGetLastError());
  41. return false;
  42. }
  43. //获得主机信息
  44. //lpHost = gethostbyname(pstrHost);
  45. //构造目标套接字地址信息
  46. saDest.sin_addr.s_addr = inet_addr(pstrHost)/**((u_long FAR *)(lpHost->h_addr))*/;
  47. saDest.sin_family = AF_INET;
  48. saDest.sin_port = 0;
  49. //ping
  50. for (nLoop = 0; nLoop < nRetries; nLoop++)
  51. {
  52. //发送ICMP回应请求
  53. SendEchoRequest(rawSocket, &saDest);
  54. nRet = WaitForEchoReply(rawSocket);
  55. if (!nRet) //没有回应,不再一个IP段
  56. {
  57. //PRINTA_INFO(pLog, "Request Timed Out");
  58. nLostConnectCnt++;
  59. }
  60. else //在一个IP段,回应正确或者回应不可达
  61. {
  62. dwTimeSent = RecvEchoReply(rawSocket,&saSrc,&cTTL); //获得回应
  63. LPCSTR strIp = inet_ntoa(saSrc.sin_addr);
  64. if (strcmp(strIp,pstrHost)==0 )
  65. {
  66. dwElapsed = GetTickCount()-dwTimeSent; //计算时间
  67. //PRINTA_INFO(pLog, "Reply from: %s: bytes=%d time=%d ms TTL=%d", strIp, REQ_DATASIZE, dwElapsed, cTTL);
  68. }
  69. else
  70. {
  71. nLostConnectCnt++;
  72. //PRINTA_INFO(pLog, "Reply from: %s: Destination host unreachable", strIp);
  73. }
  74. }
  75. }
  76. nRet = closesocket(rawSocket);
  77. if (nRet == SOCKET_ERROR)
  78. {
  79. //PRINTA_INFO(pLog, "Close Socket Error – WSAError: %ld", WSAGetLastError());
  80. }
  81. WSACleanup();
  82. if (nLostConnectCnt>=3)
  83. {
  84. bRet = false;
  85. }
  86. return bRet;
  87. }
  88. //发送ICMPECHO数据包请求
  89. int CMyPingip::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr)
  90. {
  91. static ECHOREQUEST echo;
  92. static int nId = 1;
  93. static int nSeq = 1;
  94. int nRet;
  95. //构造回应请求
  96. echo.icmpHdr.Type = 8;
  97. echo.icmpHdr.Code = 0;
  98. echo.icmpHdr.Checksum = 0;
  99. echo.icmpHdr.ID = nId++;
  100. echo.icmpHdr.Seq = nSeq++;
  101. for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
  102. {
  103. echo.cData[nRet] = ' ' + nRet;
  104. }
  105. //保存发送时间
  106. echo.dwTime = GetTickCount();
  107. echo.icmpHdr.Checksum = in_cksum((u_short *)&echo,sizeof(ECHOREQUEST));
  108. //发送请求
  109. nRet = sendto(s, (LPSTR)&echo, sizeof(ECHOREQUEST), 0, (LPSOCKADDR)lpstToAddr, sizeof(SOCKADDR_IN));
  110. if (nRet == SOCKET_ERROR)
  111. {
  112. //CString strMsg;
  113. //strMsg.Format("发送数据时发生错误 – WSAError: %ld",WSAGetLastError());
  114. //发送报错信息
  115. //SendMessage(m_hWnd,WM_MSG_STATUS,0,(LPARAM) AllocBuffer(strMsg));
  116. }
  117. return (nRet);
  118. }
  119. //接收ICMPECHO数据包回应
  120. DWORD CMyPingip::RecvEchoReply(SOCKET s,LPSOCKADDR_IN lpsaFrom,u_char *pTTL)
  121. {
  122. ECHOREPLY echoReply;
  123. int nRet;
  124. int nAddrLen = sizeof(struct sockaddr_in);
  125. //接收请求回应
  126. nRet = recvfrom(s, (LPSTR)&echoReply, sizeof(ECHOREPLY), 0, (LPSOCKADDR)lpsaFrom, &nAddrLen);
  127. //检查返回值
  128. if (nRet == SOCKET_ERROR)
  129. {
  130. //CString strMsg;
  131. //strMsg.Format("接收数据时发生错误 – WSAError: %ld",WSAGetLastError());
  132. //发送报错信息
  133. //SendMessage(m_hWnd,WM_MSG_STATUS,0,(LPARAM) AllocBuffer(strMsg));
  134. }
  135. //返回发送的时间
  136. *pTTL = echoReply.iphdr.TTL;
  137. return(echoReply.echorequest.dwTime);
  138. }
  139. //等待回应
  140. int CMyPingip::WaitForEchoReply(SOCKET s)
  141. {
  142. struct timeval Time;
  143. fd_set fds;
  144. fds.fd_count = 1;
  145. fds.fd_array[0] = s;
  146. Time.tv_sec = 1;
  147. Time.tv_usec = 0;
  148. return(select(1,&fds,NULL,NULL,&Time));
  149. }
  150. //转换地址
  151. u_short CMyPingip::in_cksum(u_short *addr,int len)
  152. {
  153. register int nleft = len;
  154. register u_short *n = addr;
  155. register u_short answer;
  156. register int sum = 0;
  157. while(nleft > 1)
  158. {
  159. sum += *n++;
  160. nleft -= 2;
  161. }
  162. if(nleft == 1)
  163. {
  164. u_short u = 0;
  165. *(u_char *)(&u) = *(u_char *)n;
  166. sum += u;
  167. }
  168. sum = (sum >> 16) + (sum & 0xffff);
  169. sum += (sum >> 16);
  170. answer = ~sum;
  171. return (answer);
  172. }