VC编程之vc实现ping
小标 2018-09-04 来源 : 阅读 2401 评论 0

摘要:本文主要向大家介绍了VC编程之vc实现ping,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

本文主要向大家介绍了VC编程之vc实现ping,通过具体的内容向大家展示,希望对大家学习VC编程有所帮助。

      
      //ping.h
      #ifndef _CPING_H_
      #define _CPING_H_
      #include 
      #include 
      #pragma pack(1)
       
      #define ICMP_ECHOREPLY  0
      #define ICMP_ECHOREQ    8
      #define REQ_DATASIZE    32      // Echo 请求数据的大小
       
      class 
CPing
      {
      public:
          //ping host, nRetries-ping次数
          bool 
Ping(LPCSTR 
pstrHost, UINT 
nRetries = 4);
       
          void 
Result(int* nElapseTime, float* fMissPack = NULL, u_char* cTTL = NULL);
          //void Result(CPing::REQ_RESULT& result);
       
      private:
          int  
WaitForEchoReply(SOCKET s);
          //ICMP回应的请求和回答函数
          int     
SendEchoRequest(SOCKET, LPSOCKADDR_IN);
          DWORD   
RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *);
          u_short in_cksum(u_short *addr, int 
len);
       
      private:
          struct 
REQ_RESULT
          {
              int         
nElapseTime;    //请求响应时间。
              u_char      cTTL;           //请求TTL(生存时间)
              float       
fMissPack;  //丢包率
          };
       
          REQ_RESULT m_Result;
      };
       
      // IP Header -- RFC 791
      typedef 
struct tagIPHDR
      {
          u_char  VIHL;           // Version and IHL
          u_char  TOS;            // Type Of Service
          short   
TotLen;         // Total Length
          short   
ID;             // Identification
          short   
FlagOff;        // Flags and Fragment Offset
          u_char  TTL;            // Time To Live
          u_char  Protocol;       // Protocol
          u_short Checksum;       // Checksum
          struct  
in_addr iaSrc;  // Internet Address - Source
          struct  
in_addr iaDst;  // Internet Address - Destination
      }IPHDR, *PIPHDR;
       
       
      // ICMP Header - RFC 792
      typedef 
struct tagICMPHDR
      {
          u_char  Type;           // Type
          u_char  Code;           // Code
          u_short Checksum;       // Checksum
          u_short ID;             // Identification
          u_short Seq;            // Sequence
          char    
Data;           // Data
      }ICMPHDR, *PICMPHDR;
       
       
       
      // ICMP Echo Request
      typedef 
struct tagECHOREQUEST
      {
          ICMPHDR icmpHdr;
          DWORD   
dwTime;
          char    
cData[REQ_DATASIZE];
      }ECHOREQUEST, *PECHOREQUEST;
       
       
      // ICMP Echo Reply
      typedef 
struct tagECHOREPLY
      {
          IPHDR   ipHdr;
          ECHOREQUEST echoRequest;
          char    
cFiller[256];
      }ECHOREPLY, *PECHOREPLY;
       
      #pragma pack()
       
      #endif
      
      //ping.cpp
      #include "ping.h"
       
      #pragma comment(lib, "ws2_32.lib")
       
      bool 
CPing::Ping(LPCSTR 
pstrHost, UINT 
nRetries)
      {
          //创建一个Raw套节字
          SOCKET rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
          if 
(rawSocket == INVALID_SOCKET) 
          {
              int 
err = WSAGetLastError();
              return 
false;
          }
          int 
nNetTimeout = 1000;//1秒 
          //发送时限
          setsockopt(rawSocket, SOL_SOCKET, SO_SNDTIMEO, (char 
*)&nNetTimeout,sizeof(int));
          //接收时限
          setsockopt(rawSocket, SOL_SOCKET, SO_RCVTIMEO, (char 
*)&nNetTimeout,sizeof(int));
       
          //获得主机信息
          LPHOSTENT lpHost = gethostbyname(pstrHost);
          if 
(lpHost == NULL)
          {
              return 
false;
          }
           
          //构造目标套节字地址信息
          struct    
sockaddr_in saDest;
          struct    
sockaddr_in saSrc;
          saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr));
          saDest.sin_family = AF_INET;
          saDest.sin_port = 3077;//0;
       
          DWORD    
dwTimeSent;
          u_char   cTTL;
          int     
nRet;
          int     
nRecvNum = 0;
          int     
nTotalTime = 0;
       
          //多次ping
          for 
(UINT nLoop = 0; nLoop < nRetries; ++nLoop)
          {
              //发送ICMP回应请求
              if 
((nRet = SendEchoRequest(rawSocket, &saDest)) < 0)
              {
                  break;
              }
       
              if 
((nRet = WaitForEchoReply(rawSocket)) == SOCKET_ERROR)
              {
                  break;
              }
              if 
(nRet)
              {
                  //获得回应
                  if 
( (dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL)) < 0)
                  {
                      nRet = dwTimeSent;
                      break;
                  }
                  //计算时间
                  nTotalTime += GetTickCount() - dwTimeSent;
                  //Sleep(1000);
                  ++nRecvNum;
              }
          }
          closesocket(rawSocket);
          if 
(nRecvNum > 0 && nRet >= 0)
          {
              m_Result.nElapseTime = nTotalTime/nRetries;
              m_Result.cTTL = cTTL;
              m_Result.fMissPack = (float)(nRetries - nRecvNum)/nRetries;
              return 
true;
          }
       
          return 
false;
      }
       
      //发送ICMPECHO数据包请求
      int 
CPing::SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) 
      {
          static 
ECHOREQUEST echoReq;
          static 
int nId = 1;
          static 
int nSeq = 1;
          int 
nRet;
       
          //构造回应请求
          echoReq.icmpHdr.Type        = ICMP_ECHOREQ;
          echoReq.icmpHdr.Code        = 0;
          echoReq.icmpHdr.Checksum    = 0;
          echoReq.icmpHdr.ID          = nId++;
          echoReq.icmpHdr.Seq         = nSeq++;
       
          for 
(nRet = 0; nRet < REQ_DATASIZE; nRet++)
              echoReq.cData[nRet] = ‘ ‘+nRet;
       
          //保存发送时间
          echoReq.dwTime  = GetTickCount();
       
          echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST));
       
          //发送请求
          nRet = sendto(s,                        
                       (LPSTR)&echoReq,           
                       sizeof(ECHOREQUEST),
                       0,                         
                       (LPSOCKADDR)lpstToAddr, 
                       sizeof(SOCKADDR_IN));   
          //检查返回值
          if 
(nRet == SOCKET_ERROR) 
          {
          }
       
          return 
(nRet);
      }
       
      //接收ICMPECHO数据包回应
      DWORD 
CPing::RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) 
      {
          ECHOREPLY echoReply;
          int 
nRet;
          int 
nAddrLen = sizeof(struct 
sockaddr_in);
       
          //接收请求回应
          nRet = recvfrom(s,                  
                          (LPSTR)&echoReply,  
                          sizeof(ECHOREPLY),  
                          0,                  
                          (LPSOCKADDR)lpsaFrom,
                          &nAddrLen);         
       
          //检查返回值
          if 
(nRet == SOCKET_ERROR) 
          {
              return 
nRet;
          }
       
          //返回发送的时间
          *pTTL = echoReply.ipHdr.TTL;
       
          return(echoReply.echoRequest.dwTime);           
      }
       
      //等待回应
      int 
CPing::WaitForEchoReply(SOCKET s)
      {
          struct 
timeval Timeout;
          fd_set readfds;
       
          readfds.fd_count = 1;
          readfds.fd_array[0] = s;
          Timeout.tv_sec = 1;
          Timeout.tv_usec = 0;
       
          return(select(1, &readfds, NULL, NULL, &Timeout));
      }
       
      //转换地址
      u_short CPing::in_cksum(u_short *addr, int 
len)
      {
          register 
int nleft = len;
          register 
u_short *w = addr;
          register 
u_short answer;
          register 
int sum = 0;
       
          while( nleft > 1 )  {
              sum += *w++;
              nleft -= 2;
          }
       
          if( nleft == 1 ) {
              u_short u = 0;
       
              *(u_char *)(&u) = *(u_char *)w ;
              sum += u;
          }
       
          sum = (sum >> 16) + (sum & 0xffff);   
          sum += (sum >> 16);           
          answer = ~sum;              
          return 
(answer);
      }
       
      void 
CPing::Result(int* nElapseTime, float* fMissPack, u_char* cTTL)
      {
          if 
(nElapseTime)
          {
              *nElapseTime = m_Result.nElapseTime;
          }
          if 
(fMissPack)
          {
              *fMissPack = m_Result.fMissPack;
          }
          if 
(cTTL)
          {
              *cTTL = m_Result.cTTL;
          }
      }

      
      //main.cpp
      #include 
      #include 
      #include 
      #include "ping.h"
       
      int main(int 
argn, char 
*argv[])
      {
          WORD 
wVersionRequested;
          WSADATA wsaData;
          int 
err;
       
          wVersionRequested = MAKEWORD( 1, 1 );
       
          err = WSAStartup( wVersionRequested, &wsaData );
       
          CPing ping;
          bool 
bResult = false;
          if 
(argn == 2)
          {
              bResult = ping.Ping(argv[1]);
          }
          else
          {
              bResult = ping.Ping("www.baidu.com");
          }
           
          std::cout << "result : " 
<< bResult << std::endl;
          if 
(bResult)
          {
              int 
nTime;
              u_char nTTL;
              float 
fMiss;
              ping.Result(&nTime, &fMiss, &nTTL);
       
              std::cout << "time : " 
<< nTime << " TTL : " 
<< (int)nTTL << " miss : " 
<< fMiss*100 << "% " 
<< std::endl;
          }
          return 
0;
      }

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言VC/MFC频道!

本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 1 不喜欢 | 0
看完这篇文章有何感觉?已经有1人表态,100%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved