ping.cpp
上传用户:may_ontech
上传日期:2007-01-08
资源大小:308k
文件大小:6k
源码类别:

图形图象

开发平台:

C++ Builder

  1. #include <winsock.h>
  2. #include "ping.h"
  3. #pragma hdrstop
  4. //---------------------------------------------------------------------------
  5. #pragma package(smart_init)
  6. #define MIN_ICMP_PACKET_SIZE 8    //minimum 8 byte icmp packet (just header)
  7. #define MAX_ICMP_PACKET_SIZE 1024 //Maximum icmp packet size
  8. // IP header
  9. typedef struct tagIP_HEADER
  10. {
  11. unsigned int h_len:4;          // length of the header
  12. unsigned int version:4;        // Version of IP
  13. unsigned char tos;             // Type of service
  14. unsigned short total_len;      // total length of the packet
  15. unsigned short ident;          // unique identifier
  16. unsigned short frag_and_flags; // flags
  17. unsigned char ttl;
  18. unsigned char proto;           // protocol (TCP, UDP etc)
  19. unsigned short checksum;       // IP checksum
  20. unsigned int sourceIP;
  21. unsigned int destIP;
  22. } IP_HEADER;
  23. typedef IP_HEADER FAR* LPIP_HEADER;
  24. // ICMP header
  25. typedef struct tagICMP_HEADER
  26. {
  27. BYTE i_type;
  28. BYTE i_code; /* type sub code */
  29. USHORT i_cksum;
  30. USHORT i_id;
  31. USHORT i_seq;
  32. /* This is not the std header, but we reserve space for time */
  33. ULONG timestamp;
  34. } ICMP_HEADER;
  35. typedef ICMP_HEADER FAR* LPICMP_HEADER;
  36. void FillIcmpData(LPICMP_HEADER pIcmp, int nData);
  37. BOOL DecodeResponse(char* pBuf, int nBytes, sockaddr_in* from);
  38. USHORT GenerateIPChecksum(USHORT* pBuffer, int nSize);
  39. /////////////////////////////////  Macros & Statics ///////////////////////////
  40. #ifdef _DEBUG
  41. #define new DEBUG_NEW
  42. #undef THIS_FILE
  43. static char THIS_FILE[] = __FILE__;
  44. #endif
  45. BOOL CPing::sm_bAttemptedIcmpInitialise = FALSE;
  46. lpIcmpCreateFile CPing::sm_pIcmpCreateFile = NULL;
  47. lpIcmpSendEcho CPing::sm_pIcmpSendEcho = NULL;
  48. lpIcmpCloseHandle CPing::sm_pIcmpCloseHandle = NULL;
  49. __int64 CPing::sm_TimerFrequency = 0;
  50. //Internal class which is used to ensure that the ICMP
  51. //handle and winsock stack is closed upon exit
  52. class _CPING
  53. {
  54. public:
  55.   _CPING();
  56. ~_CPING();
  57. protected:
  58.   HINSTANCE sm_hIcmp;
  59. friend class CPing;
  60. };
  61. _CPING::_CPING()
  62. {
  63. sm_hIcmp = NULL;
  64. }
  65. _CPING::~_CPING()
  66. {
  67. if (sm_hIcmp) {
  68.   FreeLibrary(sm_hIcmp);
  69.   sm_hIcmp = NULL;
  70. }
  71. WSACleanup();
  72. }
  73. static _CPING _cpingData;
  74. ///////////////////////////////// Implementation //////////////////////////////
  75. BOOL CPing::Initialise() const
  76. {
  77. if (!sm_bAttemptedIcmpInitialise) {
  78. sm_bAttemptedIcmpInitialise = TRUE;
  79. //Initialise the winsock stack
  80. WSADATA wsa;
  81. if (WSAStartup(MAKEWORD(1, 1), &wsa) != 0) {
  82. ShowMessage("WinSock版本不匹配n");
  83. return FALSE;
  84. }
  85. //Load up the ICMP library
  86. _cpingData.sm_hIcmp = LoadLibrary("ICMP.DLL");
  87. if (_cpingData.sm_hIcmp == NULL) {
  88. ShowMessage("无法载入'ICMP.DLL'n");
  89. return FALSE;
  90. }
  91. //Retrieve pointers to the functions in the ICMP dll
  92. sm_pIcmpCreateFile = (lpIcmpCreateFile) GetProcAddress(_cpingData.sm_hIcmp,"IcmpCreateFile");
  93. sm_pIcmpSendEcho = (lpIcmpSendEcho) GetProcAddress(_cpingData.sm_hIcmp,"IcmpSendEcho" );
  94. sm_pIcmpCloseHandle = (lpIcmpCloseHandle) GetProcAddress(_cpingData.sm_hIcmp,"IcmpCloseHandle");
  95. if (sm_pIcmpCreateFile == NULL || sm_pIcmpSendEcho == NULL ||
  96. sm_pIcmpCloseHandle == NULL)
  97. ShowMessage("'ICMP.DLL'中函数无效n");
  98. }
  99. return (sm_pIcmpCreateFile != NULL && sm_pIcmpSendEcho != NULL &&
  100.                 sm_pIcmpCloseHandle != NULL);
  101. }
  102. BOOL CPing::IsSocketReadible(SOCKET socket, DWORD dwTimeout, BOOL& bReadible)
  103. {
  104. timeval timeout = {dwTimeout/1000, dwTimeout % 1000};
  105. fd_set fds;
  106. FD_ZERO(&fds);
  107. FD_SET(socket, &fds);
  108. int nStatus = select(0, &fds, NULL, NULL, &timeout);
  109. if (nStatus == SOCKET_ERROR) {
  110. return FALSE;
  111. }
  112. else {
  113. bReadible = !(nStatus == 0);
  114. return TRUE;
  115. }
  116. }
  117. BOOL CPing::Ping(LPCTSTR pszHostName, CPingReply& pr, UCHAR nTTL, DWORD dwTimeout, UCHAR nPacketSize) const
  118. {
  119. //Make sure everything is initialised
  120. if (!Initialise())
  121.   return FALSE;
  122. LPSTR lpszAscii = (LPTSTR) pszHostName;
  123. //Convert from dotted notation if required
  124. unsigned long addr = inet_addr(lpszAscii);
  125. if (addr == INADDR_NONE) {
  126. //Not a dotted address, then do a lookup of the name
  127. hostent* hp = gethostbyname(lpszAscii);
  128. if (hp)
  129. memcpy(&addr, hp->h_addr, hp->h_length);
  130. else {
  131. ShowMessage("无法解析主机名:"+ AnsiString(pszHostName));
  132. return FALSE;
  133. }
  134. }
  135. //Create the ICMP handle
  136. HANDLE hIP = sm_pIcmpCreateFile();
  137. if (hIP == INVALID_HANDLE_VALUE) {
  138. ShowMessage("无效的'ICMP'句柄n");
  139. return FALSE;
  140. }
  141. //Set up the option info structure
  142. IP_OPTION_INFORMATION OptionInfo;
  143. ZeroMemory(&OptionInfo, sizeof(IP_OPTION_INFORMATION));
  144. OptionInfo.Ttl = nTTL;
  145. //Set up the data which will be sent
  146. unsigned char* pBuf = new unsigned char[nPacketSize];
  147. memset(pBuf, 'E', nPacketSize);
  148. //Do the actual Ping
  149. int nReplySize = sizeof(ICMP_ECHO_REPLY) + max(MIN_ICMP_PACKET_SIZE, nPacketSize);
  150. unsigned char* pReply = new unsigned char[nReplySize];
  151. ICMP_ECHO_REPLY* pEchoReply = (ICMP_ECHO_REPLY*) pReply;
  152. DWORD nRecvPackets = sm_pIcmpSendEcho(hIP, addr, pBuf, nPacketSize, &OptionInfo, pReply, nReplySize, dwTimeout);
  153. //Check we got the packet back
  154. BOOL bSuccess = (nRecvPackets == 1);
  155. //Check the IP status is OK (O is IP Success)
  156. if (bSuccess && (pEchoReply->Status != 0)) {
  157. bSuccess = FALSE;
  158. SetLastError(pEchoReply->Status);
  159. }
  160. //Check we got the same amount of data back as we sent
  161. if (bSuccess) {
  162. bSuccess = (pEchoReply->DataSize == nPacketSize);
  163. if (!bSuccess)
  164. SetLastError(ERROR_UNEXP_NET_ERR);
  165. }
  166. //Check the data we got back is what was sent
  167. if (bSuccess) {
  168. char* pReplyData = (char*) pEchoReply->Data;
  169. for (int i=0; i<nPacketSize && bSuccess; i++)
  170. bSuccess = (pReplyData[i] == 'E');
  171. if (!bSuccess)
  172. SetLastError(ERROR_UNEXP_NET_ERR);
  173. }
  174. //Close the ICMP handle
  175. sm_pIcmpCloseHandle(hIP);
  176. if (bSuccess) {
  177. //Ping was successful, copy over the pertinent info
  178. //into the return structure
  179. pr.Address.S_un.S_addr = pEchoReply->Address;
  180. pr.RTT = pEchoReply->RoundTripTime;
  181. }
  182. //Free up the memory we allocated
  183. delete [] pBuf;
  184. delete [] pReply;
  185. //return the status
  186. return bSuccess;
  187. }