11月8日icmp协议下ping命令学习

来源:互联网 发布:考研辅导班知乎 编辑:程序博客网 时间:2024/05/22 07:07
 ping命令的作用是通过icmp协议来发送数据包,
若ICMP报头为奇数个字节,会剩下最后一字节。把最后一个字节视为一个2字节数据的高    if( nleft==1)        {       *(unsigned char *)(&answer)=*(unsigned char *)w;                sum+=answer;        }        sum=(sum>>16)+(sum&0xffff);        sum+=(sum>>16);        answer=~sum;        return answer;}
"回响请求消息来验证与另一台TCP/IP计算机的IP级连接状态,
进行相关的进程调度。
获取main的进程id,用于设置ICMP的标志符
        pid=getpid();        printf("PING %s(%s): %d bytes data in ICMP packets.\n",argv[1],                        inet_ntoa(dest_addr.sin_addr),datalen);        send_packet();  /*发送所有ICMP报文*/        recv_packet();  /*接收所有ICMP报文*/        statistics(SIGALRM); /*进行统计*/        return 0;}
回响应答消息的接收情况将和往返过程的次数一起显示出来.
ping命令是用于检测网络连接性 可到达性和名称解析的疑难问题的主要TCP/IP命令.
1.基于icmp的接口函数命令,发送数据使用sendto()函数,接收数据使用recvfrom()函数。
2.把ICMP报头二进制数据以2字节为单位累加起来
        while(nleft>1)        {       sum+=*w++;                nleft-=2;        }3.设置ICMP报int pack(int pack_no){       int i,packsize;        struct icmp *icmp;        struct timeval *tval;        icmp=(struct icmp*)sendpacket;        icmp->icmp_type=ICMP_ECHO;        icmp->icmp_code=0;        icmp->icmp_cksum=0;        icmp->icmp_seq=pack_no;        icmp->icmp_id=pid;        packsize=8+datalen;        tval= (struct timeval *)icmp->icmp_data;        gettimeofday(tval,NULL);         icmp->icmp_cksum=cal_chksum( (unsigned short *)icmp,packsize);        return packsize;}sendpacket为要发送的内容,由pack()函数设定,dest_addr是目的地址,4.接收所有ICMP报文void recv_packet(){       int n,fromlen;        extern int errno;        signal(SIGALRM,statistics);        fromlen=sizeof(from);        while( nreceived<nsend)        {                       //alarm()用来设置信号SIGALRM在经过参数seconds指定的秒数后传送给目前的进程                 alarm(MAX_WAIT_TIME);                if( (n=recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,                                (struct sockaddr *)&from,&fromlen)) <0)                {       if(errno==EINTR)   continue;                        perror("recvfrom error");                        continue;                }                gettimeofday(&tvrecv,NULL);                 if(unpack(recvpacket,n)==-1)continue;                nreceived++;        }}5.求ip报头长度,即ip报头的长度标志乘4,头长度指明头中包含的4字节字的个数。可接受的最小值是5,最大值是15        iphdrlen=ip->ip_hl<<2;            icmp=(struct icmp *)(buf+iphdrlen);          len-=iphdrlen;                   if( len<8)                /*小于ICMP报头长度则不合理*/        {       printf("ICMP packets\'s length is less than 8\n");                return -1;        }  6.判断是主机名还是ip地址        if( inaddr=inet_addr(argv[1])==INADDR_NONE)        {       if((host=gethostbyname(argv[1]) )==NULL)                 {       perror("gethostbyname error");                        exit(1);                }                memcpy( (char *)&dest_addr.sin_addr,host->h_addr,host->h_length);        }        else                  dest_addr.sin_addr.s_addr = inet_addr(argv[1]);