MyPingip.cpp 4.5 KB

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