PING.CPP
上传用户:qzzxgm
上传日期:2009-12-14
资源大小:1882k
文件大小:4k
源码类别:

书籍源码

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "ping.h"
  3. void CPing::Ping(UINT nRetries,LPCSTR pstrHost,HWND hWnd)
  4. {
  5. SOCKET   rawSocket;
  6. LPHOSTENT lpHost;
  7. UINT   nLoop;
  8. int       nRet;
  9. struct    sockaddr_in saDest;
  10. struct    sockaddr_in saSrc;
  11. DWORD   dwTimeSent;
  12. DWORD   dwElapsed;
  13. u_char    cTTL;
  14. m_hWnd = hWnd;
  15. CString str;
  16. ASSERT(IsWindow(hWnd));
  17. //创建一个Raw套节字
  18. rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
  19. if (rawSocket == SOCKET_ERROR) 
  20. {
  21. WSAError("socket()");
  22. return;
  23. }
  24. //获得主机信息
  25. lpHost = gethostbyname(pstrHost);
  26. if (lpHost == NULL)
  27. {
  28. str.Format("Host not found: %s", pstrHost);
  29. ::PostMessage(m_hWnd,WM_MSG_STATUS, 0, (LPARAM) AllocBuffer(str));
  30. ::PostMessage(m_hWnd,WM_PING_END, 0, 0);
  31. return;
  32. }
  33. //构造目标套节字地址信息
  34. saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
  35. saDest.sin_family = AF_INET;
  36. saDest.sin_port = 0;
  37. //告诉用户我们现在的工作
  38. str.Format("Pinging %s [%s] with %d bytes of data:",
  39. pstrHost,
  40. inet_ntoa(saDest.sin_addr),
  41. REQ_DATASIZE);
  42. ::PostMessage(m_hWnd,WM_MSG_STATUS, 1, (LPARAM) AllocBuffer(str));
  43. //多次ping
  44. for (nLoop = 0; nLoop < nRetries; nLoop++)
  45. {
  46. //发送ICMP回应请求
  47. SendEchoRequest(rawSocket, &saDest);
  48. nRet = WaitForEchoReply(rawSocket);
  49. if (nRet == SOCKET_ERROR)
  50. {
  51. WSAError("select()");
  52. break;
  53. }
  54. if (!nRet)
  55. {
  56. str.Format("Request Timed Out");
  57. ::PostMessage(m_hWnd,WM_MSG_STATUS, 3, (LPARAM) AllocBuffer(str));
  58. }
  59. else
  60. {
  61. //获得回应
  62. dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL);
  63. //计算时间
  64. dwElapsed = GetTickCount() - dwTimeSent;
  65. str.Format("Reply[%d] from: %s: bytes=%d time=%ldms TTL=%d", 
  66. nLoop+1,
  67.    inet_ntoa(saSrc.sin_addr), 
  68.    REQ_DATASIZE,
  69.    dwElapsed,
  70.    cTTL);
  71. ::PostMessage(m_hWnd,WM_MSG_STATUS, 2, (LPARAM) AllocBuffer(str));
  72. Sleep(1000);
  73. }
  74. }
  75. ::PostMessage(m_hWnd,WM_PING_END, 0, 1);
  76. nRet = closesocket(rawSocket);
  77. if (nRet == SOCKET_ERROR)
  78. WSAError("closesocket()");
  79. }
  80. //发送ICMPECHO数据包请求
  81. int CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) 
  82. {
  83. static ECHOREQUEST echoReq;
  84. static nId = 1;
  85. static nSeq = 1;
  86. int nRet;
  87. //构造回应请求
  88. echoReq.icmpHdr.Type = ICMP_ECHOREQ;
  89. echoReq.icmpHdr.Code = 0;
  90. echoReq.icmpHdr.Checksum = 0;
  91. echoReq.icmpHdr.ID = nId++;
  92. echoReq.icmpHdr.Seq = nSeq++;
  93. for (nRet = 0; nRet < REQ_DATASIZE; nRet++)
  94. echoReq.cData[nRet] = ' '+nRet;
  95. //保存发送时间
  96. echoReq.dwTime = GetTickCount();
  97. echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));
  98. //发送请求
  99. nRet = sendto(s,
  100.  (LPSTR)&echoReq,
  101.  sizeof(ECHOREQUEST),
  102.  0,
  103.  (LPSOCKADDR)lpstToAddr, 
  104.  sizeof(SOCKADDR_IN));   
  105. if (nRet == SOCKET_ERROR) 
  106. WSAError("sendto()");
  107. return (nRet);
  108. }
  109. //接收ICMPECHO数据包回应
  110. DWORD CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) 
  111. {
  112. ECHOREPLY echoReply;
  113. int nRet;
  114. int nAddrLen = sizeof(struct sockaddr_in);
  115. //接收请求回应
  116. nRet = recvfrom(s,
  117. (LPSTR)&echoReply,
  118. sizeof(ECHOREPLY),
  119. 0,
  120. (LPSOCKADDR)lpsaFrom,
  121. &nAddrLen);
  122. //检查返回值
  123. if (nRet == SOCKET_ERROR) 
  124. WSAError("recvfrom()");
  125. //返回发送的时间
  126. *pTTL = echoReply.ipHdr.TTL;
  127. return(echoReply.echoRequest.dwTime);   
  128. }
  129. //等待回应
  130. int CPing::WaitForEchoReply(SOCKET s)
  131. {
  132. struct timeval Timeout;
  133. fd_set readfds;
  134. readfds.fd_count = 1;
  135. readfds.fd_array[0] = s;
  136. Timeout.tv_sec = 1;
  137.     Timeout.tv_usec = 0;
  138. return(select(1, &readfds, NULL, NULL, &Timeout));
  139. }
  140. //错误处理
  141. void CPing::WSAError(LPCSTR lpMsg)
  142. {
  143. CString strMsg;
  144. strMsg.Format("%s - WSAError: %ld",lpMsg,WSAGetLastError());
  145. //发送报错信息
  146. ::PostMessage(m_hWnd,WM_MSG_STATUS, 0, (LPARAM) AllocBuffer(strMsg));
  147. }
  148. //转换地址
  149. u_short CPing::in_cksum(u_short *addr, int len)
  150. {
  151. register int nleft = len;
  152. register u_short *w = addr;
  153. register u_short answer;
  154. register int sum = 0;
  155. while( nleft > 1 )  {
  156. sum += *w++;
  157. nleft -= 2;
  158. }
  159. if( nleft == 1 ) {
  160. u_short u = 0;
  161. *(u_char *)(&u) = *(u_char *)w ;
  162. sum += u;
  163. }
  164. sum = (sum >> 16) + (sum & 0xffff);
  165. sum += (sum >> 16);
  166. answer = ~sum;
  167. return (answer);
  168. }