[C++] ping命令的实现 →→→→→进入此内容的聊天室

来自 , 2019-08-23, 写在 C++, 查看 131 次.
URL http://www.code666.cn/view/6f2688a5
  1. #pragma pack(4)
  2. #include   <winsock2.h>
  3. #include   <stdlib.h>
  4. #include   <stdio.h>
  5.  
  6. #define ICMP_ECHO 8
  7. #define ICMP_ECHOREPLY 0
  8. #define ICMP_MIN 8
  9.  
  10. //#pragma comment(lib,"ws2_32.lib")
  11.  
  12. //IP数据报头
  13. typedef struct iphdr
  14. {
  15.         unsigned int h_len:4;          // length of the header  头部长
  16.         unsigned int version:4;        // Version of IP IP版本 一般都为IPV4
  17.         unsigned char tos;             // Type of service 服务类型
  18.         unsigned short total_len;      // total length of the packet 数据包总长度
  19.         unsigned short ident;          // unique identifier .唯一标识符
  20.         unsigned short frag_and_flags; // flags 标志
  21.         unsigned char ttl;                         //生存时间TTL
  22.         unsigned char proto;           // protocol (TCP, UDP etc) // 上层协议
  23.         unsigned short checksum;       // IP checksum IP校验总和
  24.         unsigned int sourceIP;             //源IP地址
  25.         unsigned int destIP;               //目的IP地址
  26. }IpHeader;
  27.  
  28. // ICMP header 定义ICMP 头部
  29. typedef struct icmphdr
  30. {
  31.         BYTE i_type;    
  32.         BYTE i_code;    
  33.         USHORT i_cksum;
  34.         USHORT i_id;    
  35.         USHORT i_seq;  
  36.         ULONG timestamp;
  37. }IcmpHeader;
  38.  
  39. #define STATUS_FAILED 0xFFFF    
  40. #define DEF_PACKET_SIZE    32
  41. #define DEF_PACKET_NUMBER  4  
  42. #define MAX_PACKET 1024      
  43. #define xmalloc(s) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,(s))
  44. #define xfree(p) HeapFree (GetProcessHeap(),0,(p))
  45.  
  46.  
  47.  
  48. USHORT checksum(USHORT *buffer, int size);
  49.  
  50. int decode_resp(char *buf, int bytes,struct sockaddr_in *from);
  51. void fill_icmp_data(char * icmp_data, int datasize);
  52.  
  53.  
  54. void Usage(char *progname)
  55. {
  56.         fprintf(stderr,"Usage:\n");
  57.         fprintf(stderr,"%s [number of packets] [data_size]\n",progname);
  58.         fprintf(stderr,"datasize can be up to 1Kb\n");
  59.         ExitProcess(STATUS_FAILED);
  60. }
  61.  
  62.  
  63. int main(int argc, char *argv[])
  64. {
  65.         WSADATA wsaData;  
  66.         SOCKET sockRaw;
  67.         struct sockaddr_in dest,from;
  68.         struct hostent *hp;  
  69.         int result,datasize,times;
  70.         int fromlen = sizeof(from);
  71.         int timeout = 1000;
  72.         int statistic = 0;
  73.         char *dest_ip;
  74.         char *icmp_data;
  75.         char *recvbuf;
  76.         unsigned int addr=0;
  77.         USHORT seq_no = 0;
  78.         if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0)
  79.         {
  80.                 fprintf(stderr,"WSAStartup failed: %d\n",GetLastError());
  81.                 ExitProcess(STATUS_FAILED);
  82.         }
  83.  
  84.         if (argc <2 )
  85.         {
  86.                 Usage(argv[0]);
  87.         }
  88.         sockRaw = WSASocket(AF_INET,SOCK_RAW,IPPROTO_ICMP,NULL, 0,WSA_FLAG_OVERLAPPED);
  89.  
  90.         if (sockRaw == INVALID_SOCKET)
  91.         {
  92.                 fprintf(stderr,"WSASocket() failed: %d\n",WSAGetLastError());
  93.                 ExitProcess(STATUS_FAILED);
  94.         }
  95.  
  96.         result = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout,sizeof(timeout));
  97.  
  98.         if(result == SOCKET_ERROR)
  99.         {
  100.                 fprintf(stderr,"failed to set recv timeout: %d\n",WSAGetLastError());
  101.                 ExitProcess(STATUS_FAILED);
  102.         }
  103.         timeout = 1000;
  104.  
  105.         result = setsockopt(sockRaw,SOL_SOCKET,SO_SNDTIMEO,(char*)&timeout,sizeof(timeout));
  106.  
  107.         if(result == SOCKET_ERROR)
  108.         {
  109.                 fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError());
  110.                 ExitProcess(STATUS_FAILED);
  111.         }
  112.         memset(&dest,0,sizeof(sockaddr_in)); /***********/
  113.  
  114.         hp = gethostbyname(argv[1]);
  115.         if (!hp)
  116.         {
  117.                 addr = inet_addr(argv[1]);
  118.         }
  119.  
  120.         if ((!hp) && (addr == INADDR_NONE) )
  121.         {
  122.                 fprintf(stderr,"Unable to resolve %s\n",argv[1]);
  123.                 ExitProcess(STATUS_FAILED);
  124.         }
  125.  
  126.         if (hp != NULL)
  127.                 memcpy(&(dest.sin_addr),hp->h_addr,hp->h_length);
  128.         else
  129.                 dest.sin_addr.s_addr = addr;
  130.  
  131.         if (hp)
  132.                 dest.sin_family = hp->h_addrtype;
  133.         else
  134.                 dest.sin_family = AF_INET;
  135.                 dest_ip = inet_ntoa(dest.sin_addr);
  136.  
  137.  
  138.         if(argc>2)
  139.         {
  140.                 times=atoi(argv[2]);
  141.                 if(times == 0)
  142.                         times=DEF_PACKET_NUMBER;
  143.         }
  144.         else
  145.                 times=DEF_PACKET_NUMBER;
  146.  
  147.         if (argc >3)
  148.         {
  149.                 datasize = atoi(argv[3]);
  150.        
  151.                         if (datasize == 0)
  152.                                 datasize = DEF_PACKET_SIZE;
  153.  
  154.          if (datasize >1024)  
  155.          {
  156.                 fprintf(stderr,"WARNING : data_size is too large !\n");
  157.                 datasize = DEF_PACKET_SIZE;
  158.          }
  159.         }
  160.         else
  161.                 datasize = DEF_PACKET_SIZE;
  162.                 datasize += sizeof(IcmpHeader);
  163.                 icmp_data = (char*)xmalloc(MAX_PACKET);
  164.                 recvbuf = (char*)xmalloc(MAX_PACKET);
  165.                 if (!icmp_data)
  166.                 {
  167.                         fprintf(stderr,"HeapAlloc failed %d\n",GetLastError());
  168.                         ExitProcess(STATUS_FAILED);
  169.                 }
  170.  
  171.         memset(icmp_data,0,MAX_PACKET);
  172.  
  173.         fill_icmp_data(icmp_data,datasize);
  174.  
  175.         fprintf(stdout,"\nPinging %s with %d of data\n\n",dest_ip,datasize);
  176.  
  177.  
  178.         for(int i=0; i<times;i++)
  179.         {
  180.                 int bwrote;
  181.        
  182.                 ((IcmpHeader*)icmp_data)->i_cksum = 0;
  183.                 ((IcmpHeader*)icmp_data)->timestamp = GetTickCount();
  184.                 ((IcmpHeader*)icmp_data)->i_seq = seq_no++;
  185.                 ((IcmpHeader*)icmp_data)->i_cksum = checksum((USHORT*)icmp_data,datasize);
  186.  
  187.                 bwrote = sendto(sockRaw,icmp_data,datasize,0,(struct sockaddr*)&dest,sizeof(dest));
  188.  
  189.                 if (bwrote == SOCKET_ERROR)
  190.                 {
  191.                         if (WSAGetLastError() == WSAETIMEDOUT)
  192.                         {
  193.                                 printf("Request timed out.\n");
  194.                                 continue;
  195.                         }
  196.                         fprintf(stderr,"sendto failed: %d\n",WSAGetLastError());
  197.                         ExitProcess(STATUS_FAILED);
  198.                 }
  199.                 if (bwrote < datasize )
  200.                 {
  201.                         fprintf(stdout,"Wrote %d bytes\n",bwrote);
  202.                 }
  203.  
  204.                 result = recvfrom(sockRaw,recvbuf,MAX_PACKET,0,(struct sockaddr*)&from,&fromlen);
  205.        
  206.                 if (result == SOCKET_ERROR)
  207.                 {
  208.                         if (WSAGetLastError() == WSAETIMEDOUT)
  209.                         {
  210.                                 printf("Request timed out.\n");
  211.                                 continue;
  212.                         }
  213.                         fprintf(stderr,"recvfrom failed: %d\n",WSAGetLastError());
  214.                         ExitProcess(STATUS_FAILED);
  215.                 }
  216.        
  217.                 if(!decode_resp(recvbuf,result,&from))
  218.                         statistic++;
  219.                 Sleep(1000);
  220.         }
  221.  
  222.  
  223.         fprintf(stdout,"\nPing statistics for %s \n",dest_ip);
  224.         fprintf(stdout,"Packets: Sent = %d,Received = %d, Lost = %d (%2.0f%% loss)\n",times,
  225.                     statistic,(times-statistic),(float)(times-statistic)/times*100);
  226.  
  227.         WSACleanup();
  228.         return 0;
  229. }
  230.  
  231. int decode_resp(char *buf, int bytes,struct sockaddr_in *from)
  232. {
  233.         IpHeader *iphdr;
  234.         IcmpHeader *icmphdr;
  235.         unsigned short iphdrlen;
  236.         iphdr = (IpHeader *)buf;  
  237.        
  238.         iphdrlen = (iphdr->h_len) * 4 ;
  239.         if (bytes < iphdrlen + ICMP_MIN)  
  240.         {
  241.                 printf("Too few bytes from %s\n",inet_ntoa(from->sin_addr));
  242.         }
  243.        
  244.         icmphdr = (IcmpHeader*)(buf + iphdrlen);
  245.         if (icmphdr->i_type != ICMP_ECHOREPLY)
  246.         {
  247.                 fprintf(stderr,"non-echo type %d recvd\n",icmphdr->i_type);
  248.                 return 1;
  249.         }
  250.        
  251.         if (icmphdr->i_id != (USHORT)GetCurrentProcessId())
  252.         {
  253.                 fprintf(stderr,"someone else's packet!\n");
  254.                 return 1;
  255.         }
  256.         printf("%d bytes from %s:",bytes, inet_ntoa(from->sin_addr));
  257.         printf(" icmp_seq = %d. ",icmphdr->i_seq);
  258.         printf(" time: %d ms ",GetTickCount()-icmphdr->timestamp);
  259.         printf("\n");
  260.         return 0;
  261. }
  262.  
  263. USHORT checksum(USHORT *buffer, int size)
  264. {
  265.         unsigned long cksum=0;
  266.        
  267.         while(size >1)
  268.         {
  269.                 cksum+=*buffer++;
  270.                 size -=sizeof(USHORT);
  271.         }
  272.          
  273.         if(size)
  274.         {
  275.                 cksum += *(UCHAR*)buffer;
  276.         }
  277.         cksum = (cksum >> 16) + (cksum & 0xffff);
  278.         cksum += (cksum >>16);  
  279.         return (USHORT)(~cksum);
  280. }
  281. /* Helper function to fill in various stuff in our ICMP request. */
  282.  
  283. void fill_icmp_data(char * icmp_data, int datasize)
  284. {
  285.         IcmpHeader *icmp_hdr;
  286.         char *datapart;
  287.         icmp_hdr = (IcmpHeader*)icmp_data;
  288.         icmp_hdr->i_type = ICMP_ECHO;
  289.         icmp_hdr->i_code = 0;
  290.         icmp_hdr->i_id = (USHORT)GetCurrentProcessId();
  291.         icmp_hdr->i_cksum = 0;
  292.         icmp_hdr->i_seq = 0;
  293.         datapart = icmp_data + sizeof(IcmpHeader);
  294.  
  295.         /* Place some junk in the buffer. */
  296.        
  297.         memset(datapart,'E', datasize - sizeof(IcmpHeader));  
  298. }
  299.  

回复 "ping命令的实现"

这儿你可以回复上面这条便签

captcha