//头文件

[cpp] view plaincopy
  1. /*
  2. * File:   CPing.h
  3. * Author: jaylong35
  4. *
  5. * Created on 2011年1月26日, 下午3:12
  6. */
  7. #ifndef CPING_H
  8. #define CPING_H
  9. #include <string>
  10. #include <signal.h>
  11. #include <arpa/inet.h>
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <unistd.h>
  15. #include <netinet/in.h>
  16. #include <netinet/ip.h>
  17. #include <netinet/ip_icmp.h>
  18. #include <netdb.h>
  19. #include <setjmp.h>
  20. #include <errno.h>
  21. #include <sys/time.h>
  22. using namespace std;
  23. #define PACKET_SIZE     4096
  24. #define SEND_DATA_LEN   56
  25. #define ERROR           -1
  26. #define SUCCESS         1
  27. #define MAX_WAIT_TIME   5
  28. #define MAX_NO_PACKETS  100
  29. class CPing
  30. {
  31. public:
  32. CPing(const char * ip, int timeout);
  33. CPing(const CPing& orig);
  34. virtual ~CPing();
  35. private:
  36. std::string m_strIp;
  37. int m_nTimeOut;
  38. int m_nPkgLen;
  39. double m_dAvgTime;
  40. double m_dFasterResponseTime;
  41. double m_dLowerResponseTime;
  42. double m_dTotalResponseTimes;
  43. int m_nSend;
  44. int m_nRecv;
  45. int m_nSocketfd;
  46. pid_t m_Pid;
  47. struct sockaddr_in m_dest_addr;
  48. struct sockaddr_in m_from;
  49. char m_sendpacket[PACKET_SIZE];
  50. char m_recvpacket[PACKET_SIZE];
  51. struct timeval m_tvrecv;
  52. public:
  53. enum
  54. {
  55. PING_FAILED,
  56. PING_SUCCEED
  57. };
  58. std::string GetIp() { return m_strIp; }
  59. int GetTimeOut() { return m_nTimeOut; }
  60. int GetPkgLen() { return m_nPkgLen; }
  61. void SetIp(const char * ip) { m_strIp = ip; }
  62. void SetTimeOut(int timeout) { m_nTimeOut = timeout; }
  63. void SetPkgLen(int pkglen) { m_nPkgLen = pkglen; }
  64. double GetAvgResponseTime() { return m_dAvgTime; }
  65. double GetFasterResponseTime() { return m_dFasterResponseTime; }
  66. double GetLowerResponseTime() { return m_dLowerResponseTime; }
  67. unsigned int GetPingStatus();
  68. static unsigned short cal_chksum(unsigned short *addr, int len);
  69. void statistics();
  70. int pack(int pack_no);
  71. void send_packet(int num);
  72. void recv_packet(void);
  73. int unpack(char *buf, int len);
  74. void tv_sub(struct timeval *out, struct timeval *in);
  75. bool ping(int times);
  76. };
  77. #endif  /* CPING_H

cpp文件

[c-sharp] view plaincopy
  1. /*
  2. * File:   CPing.cpp
  3. * Author: jaylong35
  4. *
  5. * Created on 2011年1月26日, 下午3:12
  6. */
  7. #include "CPing.h"
  8. CPing::CPing(const char * ip, int timeout)
  9. {
  10. m_strIp = ip;
  11. m_nTimeOut = timeout;
  12. m_nSend = 0;
  13. m_nRecv = 0;
  14. m_nSocketfd = 0;
  15. }
  16. CPing::CPing(const CPing& orig)
  17. {
  18. }
  19. CPing::~CPing()
  20. {
  21. }
  22. bool CPing::ping(int times)
  23. {
  24. struct hostent *host;
  25. struct protoent *protocol;
  26. unsigned long inaddr = 0l;
  27. int size = 50 * 1024;
  28. if ((protocol = getprotobyname("icmp")) == NULL)
  29. {
  30. perror("getprotobyname");
  31. return false;
  32. }
  33. /*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/
  34. if ((m_nSocketfd = socket(AF_INET, SOCK_RAW, protocol->p_proto)) < 0)
  35. {
  36. perror("socket error");
  37. exit(1);
  38. }
  39. /* 回收root权限,设置当前用户权限*/
  40. setuid(getuid());
  41. /*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的
  42. 的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/
  43. setsockopt(m_nSocketfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
  44. bzero(&m_dest_addr, sizeof (m_dest_addr));
  45. m_dest_addr.sin_family = AF_INET;
  46. /*判断是主机名还是ip地址*/
  47. if (inaddr = inet_addr(m_strIp.c_str()) == INADDR_NONE)
  48. {
  49. if ((host = gethostbyname(m_strIp.c_str())) == NULL) /*是主机名*/
  50. {
  51. perror("gethostbyname error");
  52. exit(1);
  53. }
  54. memcpy((char *) &m_dest_addr.sin_addr, host->h_addr, host->h_length);
  55. }
  56. else /*是ip地址*/
  57. memcpy((char *) &m_dest_addr, (char *) &inaddr, host->h_length);
  58. /*获取main的进程id,用于设置ICMP的标志符*/
  59. m_Pid = getpid();
  60. printf("PING %s(%s): %d bytes data in ICMP packets./n", m_strIp.c_str(),
  61. inet_ntoa(m_dest_addr.sin_addr), SEND_DATA_LEN);
  62. int i = 0;
  63. while(i < times)
  64. {
  65. i++;
  66. send_packet(1); /*发送所有ICMP报文*/
  67. recv_packet(); /*接收所有ICMP报文*/
  68. }
  69. statistics(); /*进行统计*/
  70. }
  71. unsigned short CPing::cal_chksum(unsigned short *addr, int len)
  72. {
  73. int nleft=len;
  74. int sum=0;
  75. unsigned short *w=addr;
  76. unsigned short answer=0;
  77. while(nleft > 1)
  78. {
  79. sum += *w++;
  80. nleft -= 2;
  81. }
  82. if( nleft == 1)
  83. {
  84. *(unsigned char *)(&answer) = *(unsigned char *)w;
  85. sum += answer;
  86. }
  87. sum = (sum >> 16) + (sum & 0xffff);
  88. sum += (sum >> 16);
  89. answer = ~sum;
  90. return answer;
  91. }
  92. void CPing::tv_sub(struct timeval *out,struct timeval *in)
  93. {
  94. if( (out->tv_usec-=in->tv_usec)<0)
  95. {
  96. --out->tv_sec;
  97. out->tv_usec+=1000000;
  98. }
  99. out->tv_sec-=in->tv_sec;
  100. }
  101. void CPing::statistics()
  102. {
  103. printf("/n--------------------PING statistics-------------------/n");
  104. printf("%d packets transmitted, %d received , %%%d lost/n", m_nSend, m_nRecv,
  105. (m_nSend - m_nRecv) / m_nSend * 100);
  106. close(m_nSocketfd);
  107. m_nTimeOut = m_nSend - m_nRecv;
  108. m_dAvgTime = m_dTotalResponseTimes/m_nRecv;
  109. return;
  110. }
  111. /*设置ICMP报头*/
  112. int CPing::pack(int pack_no)
  113. {
  114. int packsize;
  115. struct icmp *icmp;
  116. struct timeval *tval;
  117. icmp = (struct icmp*) m_sendpacket;
  118. icmp->icmp_type = ICMP_ECHO;
  119. icmp->icmp_code = 0;
  120. icmp->icmp_cksum = 0;
  121. icmp->icmp_seq = pack_no;
  122. icmp->icmp_id = m_Pid;
  123. packsize = 8 + SEND_DATA_LEN;
  124. tval = (struct timeval *) icmp->icmp_data;
  125. gettimeofday(tval, NULL); /*记录发送时间*/
  126. icmp->icmp_cksum = cal_chksum((unsigned short *) icmp, packsize); /*校验算法*/
  127. return packsize;
  128. }
  129. /*发送三个ICMP报文*/
  130. void CPing::send_packet(int num)
  131. {
  132. if(num > MAX_NO_PACKETS)
  133. num = MAX_NO_PACKETS;
  134. int packetsize;
  135. int i = 0;
  136. while (i < num)
  137. {
  138. i++;
  139. m_nSend++;
  140. packetsize = pack(m_nSend); /*设置ICMP报头*/
  141. if (sendto(m_nSocketfd, m_sendpacket, packetsize, 0,
  142. (struct sockaddr *) &m_dest_addr, sizeof (m_dest_addr)) < 0)
  143. {
  144. perror("sendto error");
  145. continue;
  146. }
  147. sleep(1); /*每隔一秒发送一个ICMP报文*/
  148. }
  149. }
  150. /*接收所有ICMP报文*/
  151. void CPing::recv_packet()
  152. {
  153. int n,fromlen;
  154. //signal(SIGALRM, statistics);
  155. fromlen = sizeof (m_from);
  156. while (m_nRecv < m_nSend)
  157. {
  158. alarm(MAX_WAIT_TIME);
  159. if ((n = recvfrom(m_nSocketfd, m_recvpacket, sizeof (m_recvpacket), 0,
  160. (struct sockaddr *) &m_from, (socklen_t *)&fromlen)) < 0)
  161. {
  162. if (errno == EINTR)continue;
  163. perror("recvfrom error");
  164. continue;
  165. }
  166. gettimeofday(&m_tvrecv, NULL); /*记录接收时间*/
  167. if (unpack(m_recvpacket, n) == -1)
  168. continue;
  169. m_nRecv++;
  170. }
  171. }
  172. /*剥去ICMP报头*/
  173. int CPing::unpack(char *buf,int len)
  174. {
  175. int i,iphdrlen;
  176. struct ip *ip;
  177. struct icmp *icmp;
  178. struct timeval *tvsend;
  179. double rtt;
  180. ip = (struct ip *) buf;
  181. iphdrlen = ip->ip_hl << 2; /*求ip报头长度,即ip报头的长度标志乘4*/
  182. icmp = (struct icmp *) (buf + iphdrlen); /*越过ip报头,指向ICMP报头*/
  183. len -= iphdrlen; /*ICMP报头及ICMP数据报的总长度*/
  184. if (len < 8) /*小于ICMP报头长度则不合理*/
  185. {
  186. printf("ICMP packets/'s length is less than 8/n");
  187. return -1;
  188. }
  189. /*确保所接收的是我所发的的ICMP的回应*/
  190. if ((icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == m_Pid))
  191. {
  192. tvsend = (struct timeval *) icmp->icmp_data;
  193. tv_sub(&m_tvrecv, tvsend); /*接收和发送的时间差*/
  194. rtt = m_tvrecv.tv_sec * 1000 + m_tvrecv.tv_usec / 1000; /*以毫秒为单位计算rtt*/
  195. m_dTotalResponseTimes += rtt;
  196. if(m_dFasterResponseTime == -1)
  197. {
  198. m_dFasterResponseTime = rtt;
  199. }
  200. else if(m_dFasterResponseTime > rtt)
  201. {
  202. m_dFasterResponseTime = rtt;
  203. }
  204. if(m_dLowerResponseTime == -1)
  205. {
  206. m_dLowerResponseTime = rtt;
  207. }
  208. else if(m_dLowerResponseTime < rtt)
  209. {
  210. m_dLowerResponseTime = rtt;
  211. }
  212. /*显示相关信息*/
  213. printf("%d/tbyte from %s/t: icmp_seq=%u/tttl=%d/trtt=%.3f/tms/n",
  214. len,
  215. inet_ntoa(m_from.sin_addr),
  216. icmp->icmp_seq,
  217. ip->ip_ttl,
  218. rtt);
  219. }
  220. else return -1;
  221. }

调用

[c-sharp] view plaincopy
  1. #include "CPing.h"
  2. int main()
  3. {
  4. CPing ping("192.168.10.48",100);
  5. ping.ping(20);
  6. }

运行结果

PING 192.168.10.48(0.0.0.0): 56 bytes data in ICMP packets.表明           
64      byte from 127.0.0.1     : icmp_seq=1    ttl=64  rtt=1000.000    ms 
64      byte from 127.0.0.1     : icmp_seq=2    ttl=64  rtt=1001.000    ms 
64      byte from 127.0.0.1     : icmp_seq=3    ttl=64  rtt=1001.000    ms 
64      byte from 127.0.0.1     : icmp_seq=4    ttl=64  rtt=1001.000    ms 
64      byte from 127.0.0.1     : icmp_seq=5    ttl=64  rtt=1001.000    ms 
64      byte from 127.0.0.1     : icmp_seq=6    ttl=64  rtt=1002.000    ms 
64      byte from 127.0.0.1     : icmp_seq=7    ttl=64  rtt=1001.000    ms 
64      byte from 127.0.0.1     : icmp_seq=8    ttl=64  rtt=1002.000    ms 
64      byte from 127.0.0.1     : icmp_seq=9    ttl=64  rtt=1002.000    ms 
64      byte from 127.0.0.1     : icmp_seq=10   ttl=64  rtt=1000.000    ms
64      byte from 127.0.0.1     : icmp_seq=11   ttl=64  rtt=1001.000    ms
64      byte from 127.0.0.1     : icmp_seq=12   ttl=64  rtt=1001.000    ms
64      byte from 127.0.0.1     : icmp_seq=13   ttl=64  rtt=1001.000    ms
64      byte from 127.0.0.1     : icmp_seq=14   ttl=64  rtt=1000.000    ms
64      byte from 127.0.0.1     : icmp_seq=15   ttl=64  rtt=1001.000    ms
64      byte from 127.0.0.1     : icmp_seq=16   ttl=64  rtt=1001.000    ms
64      byte from 127.0.0.1     : icmp_seq=17   ttl=64  rtt=1001.000    ms
64      byte from 127.0.0.1     : icmp_seq=18   ttl=64  rtt=1002.000    ms
64      byte from 127.0.0.1     : icmp_seq=19   ttl=64  rtt=1001.000    ms
64      byte from 127.0.0.1     : icmp_seq=20   ttl=64  rtt=1001.000    ms
                                                                                                                 
--------------------PING statistics-------------------                                          
20 packets transmitted, 20 received , %0 lost                                         
按 [Enter] 键关闭终端...

更新最新可用版本

因为很多朋友都要一个可用版本,所以今天在这里更新一下上面的程序

新版本的程序如下

.h

[cpp] view plaincopy
  1. /*
  2. * File:   CPing.h
  3. * Author: scotte.ye
  4. *
  5. * Created on 2011年1月26日, 下午3:12
  6. */
  7. #ifndef CPING_H
  8. #define CPING_H
  9. #include <string>
  10. #include <signal.h>
  11. #include <arpa/inet.h>
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <unistd.h>
  15. #include <netinet/in.h>
  16. #include <netinet/ip.h>
  17. #include <netinet/ip_icmp.h>
  18. #include <netdb.h>
  19. #include <setjmp.h>
  20. #include <errno.h>
  21. #include <sys/time.h>
  22. using namespace std;
  23. #define PACKET_SIZE     4096
  24. #define SEND_DATA_LEN   56
  25. #define ERROR           -1
  26. #define SUCCESS         1
  27. #define MAX_WAIT_TIME  20
  28. #define MAX_NO_PACKETS  4
  29. class CPing
  30. {
  31. public:
  32. CPing(const char * ip, int timeout);
  33. CPing(const CPing& orig);
  34. virtual ~CPing();
  35. private:
  36. std::string m_strIp;
  37. std::string m_Ip;
  38. int m_nTimeOut;
  39. int m_nPkgLen;
  40. double m_dAvgTime;
  41. double m_dFasterResponseTime;
  42. double m_dLowerResponseTime;
  43. double m_dTotalResponseTimes;
  44. int m_nSend;
  45. int m_nRecv;
  46. int m_nSocketfd;
  47. pid_t m_Pid;
  48. struct sockaddr_in m_dest_addr;
  49. struct sockaddr_in m_from;
  50. char m_sendpacket[PACKET_SIZE];
  51. char m_recvpacket[PACKET_SIZE];
  52. struct timeval m_tvrecv;
  53. bool m_bTimeOut;
  54. //add by scotte.ye 2011-07-27
  55. int m_nMaxTimeWait;
  56. int m_nMaxTestpkg;
  57. public:
  58. enum
  59. {
  60. PING_FAILED,
  61. PING_SUCCEED
  62. };
  63. void SetMaxTimeWait(int nMaxTimeWait) { m_nMaxTimeWait = nMaxTimeWait; }
  64. void SetMaxTestpkg(int nMaxTestpkg) { m_nMaxTestpkg = nMaxTestpkg; }
  65. void SetPingManager(CPingManager * pPingManager) { m_pPingManager = pPingManager; }
  66. int GetSuccessTimes() { return m_nRecv; }
  67. std::string GetIp() { return m_Ip; }
  68. int GetTimeOut() { return m_nTimeOut; }
  69. int GetPkgLen() { return m_nPkgLen; }
  70. void SetIp(const char * ip) { m_strIp = ip; }
  71. void SetTimeOut(int timeout) { m_nTimeOut = timeout; }
  72. void SetPkgLen(int pkglen) { m_nPkgLen = pkglen; }
  73. double GetAvgResponseTime() { return m_dAvgTime; }
  74. double GetFasterResponseTime() { return m_dFasterResponseTime; }
  75. double GetLowerResponseTime() { return m_dLowerResponseTime; }
  76. unsigned int GetPingStatus();
  77. static unsigned short cal_chksum(unsigned short *addr, int len);
  78. //void statistics(int sig);
  79. int pack(int pack_no);
  80. void send_packet(void);
  81. void recv_packet(void);
  82. int unpack(char *buf, int len);
  83. void tv_sub(struct timeval *out, struct timeval *in);
  84. bool ping(int times);
  85. void statistics(int sig);
  86. bool CreateSocket();
  87. bool CloseSocket();
  88. //double ping_m();
  89. };
  90. #endif  /* CPING_H */

cpp

[cpp] view plaincopy
  1. /*
  2. * File:   CPing.cpp
  3. * Author: scotte.ye
  4. *
  5. * Created on 2011年1月26日, 下午3:12
  6. */
  7. #include "CPing.h"
  8. #include "CPingManager.h"
  9. #include "include/Log/CLog.h"
  10. #include <sys/types.h>
  11. #include <fcntl.h>
  12. #define gettid() syscall(224)
  13. void CPing::statistics(int sig)
  14. {
  15. printf("------statistics------\n");
  16. printf("%d packets transmitted, %d received , %%%d lost\n", m_nSend, m_nRecv,
  17. (m_nSend - m_nRecv) / m_nSend * 100);
  18. //close(m_nSocketfd);
  19. m_nTimeOut = m_nSend - m_nRecv;
  20. m_dAvgTime = m_dTotalResponseTimes/m_nRecv;
  21. // m_bTimeOut = true;
  22. }
  23. CPing::CPing(const char * ip, int timeout)
  24. {
  25. m_strIp = ip;
  26. m_Ip = ip;
  27. m_nTimeOut = 0;
  28. m_nSend = 0;
  29. m_nRecv = 0;
  30. m_nSocketfd = 0;
  31. m_dFasterResponseTime = -1;
  32. m_dLowerResponseTime = -1;
  33. m_dAvgTime = -1;
  34. m_dTotalResponseTimes = 0;
  35. m_pPingManager = NULL;
  36. if(timeout > MAX_WAIT_TIME)
  37. m_nMaxTimeWait = MAX_WAIT_TIME;
  38. else
  39. m_nMaxTimeWait = timeout;
  40. m_nMaxTestpkg = MAX_NO_PACKETS;
  41. }
  42. CPing::CPing(const CPing& orig)
  43. {
  44. }
  45. CPing::~CPing()
  46. {
  47. CloseSocket();
  48. }
  49. bool CPing::CreateSocket()
  50. {
  51. CloseSocket();
  52. struct hostent hostinfo,*host;
  53. char buf[2048];
  54. struct protoent *protocol;
  55. unsigned long inaddr = 0l;
  56. int size = 50 * 1024;
  57. if ((protocol = getprotobyname("icmp")) == NULL)
  58. {
  59. printf("CreateSocket: getprotobyname failed:%d\n",errno);
  60. return false;
  61. }
  62. /*生成使用ICMP的原始套接字,这种套接字只有root才能生成*/
  63. if ((m_nSocketfd = socket(AF_INET, SOCK_RAW, protocol->p_proto)) < 0)
  64. {
  65. printf("CreateSocket: create socket failed:%d\n",errno);
  66. return false;
  67. }
  68. /* 回收root权限,设置当前用户权限*/
  69. setuid(getuid());
  70. /*扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的
  71. 的可能性,若无意中ping一个广播地址或多播地址,将会引来大量应答*/
  72. int nRet = setsockopt(m_nSocketfd, SOL_SOCKET, SO_RCVBUF, &size, sizeof (size));
  73. if(nRet != 0)
  74. {
  75. printf("CreateSocket: set socket receive buf failed:%d\n",errno);
  76. return false;
  77. }
  78. bzero(&m_dest_addr, sizeof (m_dest_addr));
  79. m_dest_addr.sin_family = AF_INET;
  80. /*判断是主机名还是ip地址*/
  81. if ((inaddr = inet_addr(m_strIp.c_str())) == INADDR_NONE)
  82. {
  83. int nret;
  84. gethostbyname_r(m_strIp.c_str(), &hostinfo, buf, sizeof(buf), &host, &nret);
  85. if (nret != 0) /*是主机名*/
  86. {
  87. printf("CreateSocket: gethostbyname error %s failed:%d\n",m_strIp.c_str(),errno);
  88. return false;
  89. }
  90. memcpy((char *) &m_dest_addr.sin_addr, host->h_addr, host->h_length);
  91. }
  92. else /*是ip地址*/
  93. memcpy((char *) &m_dest_addr.sin_addr, (char *) &inaddr, sizeof(inaddr));
  94. m_Ip = inet_ntoa(m_dest_addr.sin_addr);
  95. return true;
  96. }
  97. bool CPing::CloseSocket()
  98. {
  99. if(m_nSocketfd !=0)
  100. close(m_nSocketfd);
  101. m_nSocketfd = 0;
  102. return true;
  103. }
  104. bool CPing::ping(int times)
  105. {
  106. int i = 0;
  107. while(i < times)
  108. {
  109. bool bRet = CreateSocket();
  110. if(!bRet)
  111. {
  112. printf("ping: create socket falied!\n");
  113. return false;
  114. }
  115. /*获取main的进程id,用于设置ICMP的标志符*/
  116. int nh = gettid();
  117. nh = nh<<8;
  118. time_t t;
  119. time(&t);
  120. int nt = t;
  121. nh = nh&0xff00;
  122. nt = nt&0xff;
  123. m_Pid = nt|nh;
  124. printf("PING %s(%s): %d bytes data in ICMP packets.\n", m_strIp.c_str(),
  125. m_Ip.c_str(), SEND_DATA_LEN);
  126. i++;
  127. m_nSend = 0;
  128. m_nRecv = 0;
  129. send_packet(); /*发送所有ICMP报文*/
  130. recv_packet(); /*接收所有ICMP报文*/
  131. //statistics(SIGALRM); /*进行统计*/
  132. if(m_nRecv > 0)
  133. break;
  134. }
  135. m_bTimeOut = false;
  136. if(m_nRecv > 0)
  137. {
  138. m_nTimeOut = m_nSend - m_nRecv;
  139. m_dAvgTime = m_dTotalResponseTimes/m_nRecv;
  140. }
  141. else
  142. {
  143. m_nTimeOut = m_nSend;
  144. m_dAvgTime = -1;
  145. return false;
  146. }
  147. return true;
  148. }
  149. unsigned short CPing::cal_chksum(unsigned short *addr, int len)
  150. {
  151. int nleft=len;
  152. int sum=0;
  153. unsigned short *w=addr;
  154. unsigned short answer=0;
  155. while(nleft > 1)
  156. {
  157. sum += *w++;
  158. nleft -= 2;
  159. }
  160. if( nleft == 1)
  161. {
  162. *(unsigned char *)(&answer) = *(unsigned char *)w;
  163. sum += answer;
  164. }
  165. sum = (sum >> 16) + (sum & 0xffff);
  166. sum += (sum >> 16);
  167. answer = ~sum;
  168. return answer;
  169. }
  170. void CPing::tv_sub(struct timeval *out,struct timeval *in)
  171. {
  172. if( (out->tv_usec-=in->tv_usec)<0)
  173. {
  174. --out->tv_sec;
  175. out->tv_usec+=1000000;
  176. }
  177. out->tv_sec-=in->tv_sec;
  178. }
  179. /*设置ICMP报头*/
  180. int CPing::pack(int pack_no)
  181. {
  182. int packsize;
  183. struct icmp *icmp;
  184. struct timeval *tval;
  185. icmp = (struct icmp*) m_sendpacket;
  186. icmp->icmp_type = ICMP_ECHO;
  187. icmp->icmp_code = 0;
  188. icmp->icmp_cksum = 0;
  189. icmp->icmp_seq = pack_no;
  190. icmp->icmp_id = m_Pid;
  191. packsize = 8 + SEND_DATA_LEN;
  192. tval = (struct timeval *) icmp->icmp_data;
  193. gettimeofday(tval, NULL); /*记录发送时间*/
  194. icmp->icmp_cksum = cal_chksum((unsigned short *) icmp, packsize); /*校验算法*/
  195. return packsize;
  196. }
  197. /*发送三个ICMP报文*/
  198. void CPing::send_packet()
  199. {
  200. int packetsize;
  201. while (m_nSend < m_nMaxTestpkg)
  202. {
  203. m_nSend++;
  204. packetsize = pack(m_nSend); /*设置ICMP报头*/
  205. if (sendto(m_nSocketfd, m_sendpacket, packetsize, 0,
  206. (struct sockaddr *) &m_dest_addr, sizeof (m_dest_addr)) < 0)
  207. {
  208. printf("send_packet: send error :%d\n",errno);
  209. continue;
  210. }
  211. usleep(2); /*每隔一秒发送一个ICMP报文*/
  212. }
  213. }
  214. /*接收所有ICMP报文*/
  215. void CPing::recv_packet()
  216. {
  217. int n,fromlen;
  218. while(m_nRecv < m_nSend)
  219. {
  220. struct timeval timeo;
  221. fd_set readfds;
  222. FD_ZERO(&readfds);
  223. FD_SET(m_nSocketfd,&readfds);
  224. int maxfds = m_nSocketfd +1;
  225. timeo.tv_sec = m_nMaxTimeWait;
  226. timeo.tv_usec = 0;
  227. n = select(maxfds,&readfds,NULL,NULL,&timeo);
  228. if(n == 0)
  229. {
  230. printf("recv_packet: select time out :%d",errno);
  231. return ;
  232. }
  233. else if(n < 0)
  234. {
  235. printf("recv_packet: select error :%d",errno);
  236. if(errno == EINTR)
  237. {
  238. printf("recv_packet: select error :%d",errno);
  239. continue;
  240. }
  241. else
  242. {
  243. printf("recv_packet: select error :%d",errno);
  244. return ;
  245. }
  246. }
  247. if ((n = recvfrom(m_nSocketfd, m_recvpacket, sizeof (m_recvpacket), 0,
  248. (struct sockaddr *) &m_from, (socklen_t *)&fromlen)) <= 0)
  249. {
  250. printf("recv_packet: recv error :%d",errno);
  251. return;
  252. }
  253. gettimeofday(&m_tvrecv, NULL); /*记录接收时间*/
  254. if (unpack(m_recvpacket, n) == -1)
  255. {
  256. continue;
  257. }
  258. m_nRecv++;
  259. }
  260. //return ;
  261. }
  262. /*剥去ICMP报头*/
  263. int CPing::unpack(char *buf,int len)
  264. {
  265. int i,iphdrlen;
  266. struct ip *ip;
  267. struct icmp *icmp;
  268. struct timeval *tvsend;
  269. double rtt;
  270. ip = (struct ip *) buf;
  271. iphdrlen = ip->ip_hl << 2; /*求ip报头长度,即ip报头的长度标志乘4*/
  272. icmp = (struct icmp *) (buf + iphdrlen); /*越过ip报头,指向ICMP报头*/
  273. len -= iphdrlen; /*ICMP报头及ICMP数据报的总长度*/
  274. if (len < 8) /*小于ICMP报头长度则不合理*/
  275. {
  276. printf( "ICMP packets\'s length is less than 8");
  277. return -1;
  278. }
  279. /*确保所接收的是我所发的的ICMP的回应*/
  280. if ((icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == m_Pid)&&(m_Ip == inet_ntoa(m_from.sin_addr)))
  281. {
  282. tvsend = (struct timeval *) icmp->icmp_data;
  283. tv_sub(&m_tvrecv, tvsend); /*接收和发送的时间差*/
  284. rtt = m_tvrecv.tv_sec * 1000 + m_tvrecv.tv_usec / 1000; /*以毫秒为单位计算rtt*/
  285. m_dTotalResponseTimes += rtt;
  286. if(m_dFasterResponseTime == -1)
  287. {
  288. m_dFasterResponseTime = rtt;
  289. }
  290. else if(m_dFasterResponseTime > rtt)
  291. {
  292. m_dFasterResponseTime = rtt;
  293. }
  294. if(m_dLowerResponseTime == -1)
  295. {
  296. m_dLowerResponseTime = rtt;
  297. }
  298. else if(m_dLowerResponseTime < rtt)
  299. {
  300. m_dLowerResponseTime = rtt;
  301. }
  302. /*显示相关信息*/
  303. printf("%d\tbyte from %s\t: icmp_seq=%u\tttl=%d\trtt=%.3f\tms\n",
  304. len,
  305. inet_ntoa(m_from.sin_addr),
  306. icmp->icmp_seq,
  307. ip->ip_ttl,
  308. rtt);
  309. }
  310. else
  311. {
  312. printf("throw away the old package %d\tbyte from %s\t: icmp_seq=%u\tttl=%d\trtt=%.3f\tms",
  313. len,
  314. inet_ntoa(m_from.sin_addr),
  315. icmp->icmp_seq,
  316. ip->ip_ttl,
  317. rtt);
  318. return -1;
  319. }
  320. }

转载于:https://www.cnblogs.com/daochong/p/6873543.html

c++ 实现ping相关推荐

  1. linux下出现ping:unknown host www.baidu.com问题时的解决办法——ubuntu下局域网络的配置...

    如果ping域名的时候出现ping:unknown host  xxx.xxx 但是ping IP地址的时候可以通的话 可知是dns服务器没有配置好, 查看一下配置文件/etc/resolv.conf ...

  2. CMD——ping及用其检测网络故障

    Ping命令全称Packet Internet Grope,即因特网包探测器.通过调用ICMP(因特网控制报文协议),发送一份ICMP回显请求给目的主机,并等待返回ICMP回显应答.一般用来测试源主机 ...

  3. RedHat 7.0及CentOS 7.0禁止Ping的三种方法

    作者:荒原之梦 原文链接:http://zhaokaifeng.com/?p=538 前言: "Ping"属于ICMP协议(即"Internet控制报文协议") ...

  4. 【Ubuntu】ping: unknown host www.baidu.com

    1.问题描述 每次重新设置网络后,ping百度总是报错: $ ping www.baidu.com ping: unknown host www.baidu.com 2.原因分析 原因是:查看/etc ...

  5. 10 ping不通widwos7 windwos_弱电老司机总结的10种视频监控系统故障解决方法,学会,事半功倍...

    最近有许多的读者咨询关于视频监控系统维修方法的事情,有没有总结一些常见故障的解决方案呢?当然有的,今天分享一些常见故障解决方法. 正文: 视频监控系统通常出现摄像机没有画面.或者画面卡顿.丢失等情况, ...

  6. centos iptables关于ping

    配置iptables策略后,一般来说INPUT都是DROP然后配置需要通过的 当执行: iptables -P INPUT DROP 后,机器就不能被ping通了! 因为icmp没有添加到规则中! 于 ...

  7. 服务器ping你可以ping通,你ping服务器ping不同的解决方案!!

    这几天让公司的服务器弄的蛋疼啊!!三天两头的出问题,主管脸色不大好看,我这里也郁闷的要死.所以发誓一定要把好安全关!! 今天在自己的虚拟机上边装了一个winserver2003标准版,搭建好环境之后发 ...

  8. 响应因特网端口ping命令_如何使用Ping命令识别基本的Internet问题

    响应因特网端口ping命令 Next time you call your help desk, do you want to wow them with your networking knowle ...

  9. 电脑显示服务器地址无法ping通,网关无法Ping通故障及解决方法

    很多网络故障是常见问题,一般的三板斧方法就能解决问题,但有些故障容易让我们多走弯路,我们不妨拓宽故障排查范围,换换思路. 在与网络亲密接触的过程中,我们或多或少地会遇到一些网络故障,对于许多网络故障来 ...

  10. 海思涵科技WIFI认证服务器不在线,在海思平台外加一个usb wifi模块,mt7601 加载ok,配置网络ok,但不能ping通?...

    请教下:我用mt7601 usb wifi模块 加载驱动 配置网络后经常打印 PeerBeaconAtJoinAction(): Set CentralChannel=1 PeerBeaconAtJo ...

最新文章

  1. 教育部回应:没有使用“第一学历”这个概念!
  2. Android的数据存储
  3. Java yield详解_Java 中的 yield 关键字
  4. Chapter 3 Phenomenon——19
  5. 比亚迪定薪后多久给offer_比亚迪车主给爱车做四门隔音,没想到两年后肠子都悔青...
  6. Qt编程'hello world
  7. 怎么看铜皮属性_阻抗匹配怎么做 及阻抗匹配的作用。
  8. java实现小说采集_Java实现一个小说采集程序的简单实例
  9. 3D次时代来临 如何玩转红蓝立体游戏
  10. 把unc0ver.ipa重签名后安装到手机上实现越狱
  11. oppo小布机器人_OPPO小布助手喜迎重大升级,你的私人全能管家现已上线!
  12. 计算机底层知识之运行环境可执行文件
  13. 服务器虚拟化用什么显卡,显卡虚拟化使用及配置技术
  14. Android 4.0.4系统下实现apk的静默安装和启动
  15. 一篇文章搞懂php文件系统基本操作
  16. 今日份安利:手机上怎么去图片水印
  17. git ------ git clone方法总结(可直接加账户和密码)
  18. 投资基建无异扩大货币供应
  19. 视频教程-系统集成项目管理工程师考试-技术部分-软考
  20. 百度AI学习第一天_调用API接口通用步骤

热门文章

  1. 吴恩达深度学习2.2笔记_Improving Deep Neural Networks_优化算法
  2. 同一路由带参刷新,以及params和query两种方式传参的异同
  3. 彻底删除0KB顽固文件或文件夹的方法
  4. 品《阿里巴巴大数据实践-大数据之路》一书(上)
  5. 关于头文件,全局变量,extern,static
  6. java文件格式转换
  7. Leetcode 1015. Smallest Integer Divisible by K
  8. SQL基础(八)-- sql左右连接中的on and 和 on where 的区别
  9. docker 清理容器的一些命令,彻底或选择清理
  10. webpack打包样式代码去重