• 自己动手写一个简单的ping命令(windows下)


    计算机网络的一个作业:实现ping+ip 不要求其它参数

    用到的知识:ip报头结构,icmp报头结构,获取主机ip方法,winsock的简单操作

    实现的结果:一般的ip能够ping通,如www.baidu.com, www.sina.com.cn

    存在的问题:本机(127.0.0.1)ping不通  

      1 /*
      2 *filename:ping.c
      3 *author:ChrisZZ
      4 */
      5 #pragma comment(lib, "ws2_32.lib")
      6 #include <stdio.h>
      7 #include <winsock2.h>
      8 #include <ws2tcpip.h>
      9 #include <process.h>
     10 
     11 
     12 struct IPHeader{//IPv4头部结构
     13     unsigned char ver_hlen;//头部长度,用4位表示,range[5,15]
     14     //  unsigned int ver:4;//version
     15     unsigned char tos;//type of service
     16     unsigned short total_len;
     17     unsigned short id;
     18     unsigned short frags_and_flags;
     19     unsigned char ttl;//time to live
     20     unsigned char proto;//protocal
     21     unsigned short chksum;//checksum
     22     unsigned int srcIp;//source IP
     23     unsigned int dstIp;//destination IP
     24 };
     25 
     26 struct ICMPHeader{//ICMP头部结构
     27     unsigned char type;
     28     unsigned char code;
     29     unsigned short chksum;
     30     unsigned short id;
     31     unsigned short seq;//sequence
     32     unsigned int timestamp;
     33 };
     34 
     35 #define ICMP_ECHO       8
     36 #define ICMP_ECHO_REPLY 0
     37 #define  PACKAGE_SIZE         sizeof(IPHeader)+sizeof(ICMPHeader)
     38 void usage();
     39 unsigned short CheckSum(unsigned short*, int);
     40 void HandleError(char *);
     41 
     42 //用法说明函数
     43 void usage(){
     44     printf("用法:ping 目标主机\n\n");
     45     system("pause");
     46 }
     47 
     48 //错误处理函数
     49 void HandleError(char *str){
     50     int errCode=WSAGetLastError();
     51 
     52     char info[65]={0};
     53     _snprintf(info, 64, "%s:  %d\n", str, errCode);
     54     printf(info);
     55 }
     56 
     57 unsigned short checksum(unsigned short* buff, int size){
     58     unsigned int chksum=0;
     59     while(size>1){
     60         chksum+=*buff++;
     61         size-=sizeof(unsigned short);
     62     }
     63     if(size){
     64         chksum+=*(unsigned char*)(buff);
     65     }
     66     chksum=(chksum>>16)+(chksum &0xffff);
     67     chksum+=(chksum>>16);
     68     return (unsigned short)(~chksum);
     69 }
     70 
     71 void FillPackage(char *pData, unsigned int dstIP, unsigned short id){
     72     memset(pData, 0, PACKAGE_SIZE);
     73 
     74     IPHeader *pIPHeader=(IPHeader*)pData;
     75 
     76     int nVersion=4;
     77     int nHeadSize=sizeof(IPHeader)/4;
     78 
     79     //获得本机IP
     80     struct sockaddr_in SrcAddr;
     81     struct hostent * hpsrc;
     82     char localhost[32];
     83     gethostname(localhost, sizeof(localhost));
     84     hpsrc=gethostbyname(localhost);
     85     memset(&SrcAddr, 0, sizeof(SrcAddr));
     86     memcpy(&(SrcAddr.sin_addr), hpsrc->h_addr, hpsrc->h_length);
     87     SrcAddr.sin_port=htons(0);
     88     SrcAddr.sin_family=AF_INET;
     89 
     90 
     91     unsigned int srcIP=SrcAddr.sin_addr.s_addr;//本机IP
     92     unsigned int destIp=dstIP;
     93     pIPHeader->ver_hlen=(nVersion<<4)|nHeadSize;
     94     pIPHeader->tos=0;
     95     pIPHeader->total_len=htons(PACKAGE_SIZE);
     96     pIPHeader->id=htons(1234);//????
     97     pIPHeader->frags_and_flags=0;
     98     pIPHeader->ttl=255;//??
     99     pIPHeader->proto=IPPROTO_ICMP;
    100     pIPHeader->chksum=0;
    101     pIPHeader->srcIp=srcIP;
    102     pIPHeader->dstIp=dstIP;
    103 
    104     pIPHeader->chksum=checksum((unsigned short*)pData, sizeof(IPHeader));
    105     ICMPHeader* pICMPHeader=(ICMPHeader*)(pData+sizeof(IPHeader));
    106     pICMPHeader->type=ICMP_ECHO;
    107     pICMPHeader->code=0;
    108     pICMPHeader->chksum=0;
    109     pICMPHeader->id=htons(id);
    110     pICMPHeader->seq=htons(id);
    111     pICMPHeader->chksum=checksum((unsigned short*)((char*)pData+sizeof(IPHeader)), sizeof(ICMPHeader));
    112 
    113 }
    114 
    115 int main(int argc, char* argv[]){
    116 
    117     //初始化
    118     WSADATA wsaData;
    119     struct sockaddr_in DestAddr,from;
    120     IPHeader *ip;
    121     ICMPHeader *icmp;
    122     ICMPHeader *SendIcmp;
    123     int Timeout=1000;
    124     char IcmpBuffer[PACKAGE_SIZE]="";
    125     SOCKET IcmpSocket;
    126     char RecvBuffer[1024];
    127     sockaddr_in addr;
    128     int Len = sizeof(addr);
    129     int Result;
    130     struct hostent * hpdst;
    131     int pid=_getpid();
    132     struct timeval tv;
    133     fd_set readSet;
    134     BOOL bBroadcast=false;
    135 
    136     //确定参数个数
    137     if(argc!=2){
    138         printf("参数不正确\n");
    139         usage();
    140         return -1;
    141     }
    142 
    143 
    144     if ((Result = WSAStartup(MAKEWORD(2, 2), &wsaData)) != 0){
    145         printf("WSAStartup failed with error %d\n", Result);
    146         return 0;
    147     }
    148 
    149 
    150     //获取目的主机IP
    151     hpdst=gethostbyname(argv[1]);
    152     if(hpdst==NULL){
    153         HandleError("gethostbyname");
    154         WSACleanup();
    155         return -1;
    156     }
    157 
    158     //创建ICMP封包并发送
    159     //char buff[sizeof(ICMP_HDR)+32];
    160     IcmpSocket=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
    161     if(IcmpSocket==INVALID_SOCKET){
    162         HandleError("socket");
    163         WSACleanup();
    164         return -1;
    165     }
    166     BOOL on=TRUE;
    167     Result=setsockopt(IcmpSocket,IPPROTO_IP,IP_HDRINCL, (char*)&on, sizeof(on));
    168     if(Result==SOCKET_ERROR){
    169         HandleError("socketopt");
    170         WSACleanup();
    171         return -1;  
    172     }   
    173     memset(&DestAddr, 0, sizeof(DestAddr));
    174     memcpy(&(DestAddr.sin_addr), hpdst->h_addr, hpdst->h_length);
    175     DestAddr.sin_port=htons(0);
    176     /*reference:http://www.cnblogs.com/CBDoctor/archive/2012/10/28/2743109.html*/
    177     DestAddr.sin_family=AF_INET;
    178 
    179 
    180 
    181     int i;
    182     for(i=0; i<3; i++){
    183        if(i==0) printf("正在Ping %s 具有 %d 字节的数据:\n", inet_ntoa(DestAddr.sin_addr), 32);
    184 
    185         FillPackage(IcmpBuffer, DestAddr.sin_addr.s_addr/*dstIp*/, (unsigned short)pid);
    186 
    187         Result=sendto(IcmpSocket, IcmpBuffer, PACKAGE_SIZE, 0, (struct sockaddr*)&DestAddr, sizeof(DestAddr));
    188         if(Result==SOCKET_ERROR){
    189             HandleError("sendto");
    190             break;
    191         }
    192 
    193         while (1){
    194             tv.tv_sec=3;
    195             tv.tv_usec=0;
    196             FD_ZERO(&readSet);
    197             FD_SET(IcmpSocket,&readSet);
    198 
    199             int res=select(IcmpSocket+1,&readSet,NULL,NULL,&tv);
    200             if(res==SOCKET_ERROR){
    201                 HandleError("select");
    202                 break;
    203             }
    204             if(res==0){
    205                 if(!bBroadcast)
    206                     printf("请求超时。\n");
    207                 break;
    208             }
    209             if(FD_ISSET(IcmpSocket, &readSet)){
    210                 memset(IcmpBuffer,0, PACKAGE_SIZE);
    211                 memset(&from,0,sizeof(from));
    212                 int len=sizeof(from);
    213                 if(recvfrom(IcmpSocket, IcmpBuffer, PACKAGE_SIZE,0,(struct sockaddr*) &from, &len)==SOCKET_ERROR)
    214                 {
    215                     HandleError("recvfrom");
    216                     break;
    217                 }
    218 
    219                 IPHeader *pIPHdr=(IPHeader *) IcmpBuffer;
    220                 ICMPHeader *pICMPHdr=(ICMPHeader*)(IcmpBuffer+sizeof(IPHeader));
    221                 int nTime = GetTickCount() - pICMPHdr->timestamp;  
    222                 if(pICMPHdr->id==htons((u_short) pid)&&pICMPHdr->seq==htons((u_short) pid)
    223                     &&pICMPHdr->type==ICMP_ECHO_REPLY){
    224                         printf("来自 %s 的回复: 字节=%d time=%dms\n",inet_ntoa(from.sin_addr), Result, pIPHdr->ttl);
    225                         if (!bBroadcast) break;
    226                 } 
    227             }
    228         }//end of while
    229         Sleep(1000);
    230     }
    231 
    232     //关闭套接字
    233     closesocket(IcmpSocket);
    234     WSACleanup();
    235     system("pause");
    236     return 0;
    237 }
    Greatness is never a given, it must be earned.
  • 相关阅读:
    数组指针和指针数组
    C#反射机制
    浅探委托(delegate)和事件(event)
    C#的is和as操作符来进行强制类型转换&&值类型的拆箱、装箱
    2018-2-8
    JSP--语法
    JSP中的<%%>,<%! %>,<%= %>,<%-- --%>
    JSP--简介
    springmvc实现文件下载到Android手机设备pda端
    常用的正则表达式(转)
  • 原文地址:https://www.cnblogs.com/zjutzz/p/3129603.html
Copyright © 2020-2023  润新知