void DecodeICMPHeader(char *buf, int bytes, 
    struct sockaddr_in *from)//调试的时候发现buf中包含bytes个'E',buf是接受缓冲区
{
    IpHeader       *iphdr = NULL;
    IcmpHeader     *icmphdr = NULL;
    unsigned short  iphdrlen;
    DWORD           tick;
    static   int    icmpcount = 0;    iphdr = (IpHeader *)buf;//为什么强制转换就能转换成ip头呢
// Number of 32-bit words * 4 = bytes
    iphdrlen = iphdr->h_len * 4;
    tick = GetTickCount();    if ((iphdrlen == MAX_IP_HDR_SIZE) && (!icmpcount))
        DecodeIPOptions(buf, bytes);    if (bytes  < iphdrlen + ICMP_MIN) 
    {
        printf("Too few bytes from %s\n", 
            inet_ntoa(from->sin_addr));
    }
    icmphdr = (IcmpHeader*)(buf + iphdrlen);    if (icmphdr->i_type != ICMP_ECHOREPLY) 
    {
        printf("nonecho type %d recvd\n", icmphdr->i_type);
        return;
    }
    // Make sure this is an ICMP reply to something we sent!
    //
    if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) 
    {
        printf("someone else's packet!\n");
        return ;
    }
    printf("%d bytes from %s:", bytes, inet_ntoa(from->sin_addr));
    printf(" icmp_seq = %d. ", icmphdr->i_seq);
    printf(" time: %d ms", tick - icmphdr->timestamp);
    printf("\n");    icmpcount++;
    return;
}

解决方案 »

  1.   

    是PING的一个接收部分进行解码的程序。
    解码ICMP报文的程序void DecodeICMPHeader(char *buf, int bytes, 
        struct sockaddr_in *from)//调试的时候发现buf中包含bytes个'E',buf是接受缓冲区
    {
        IpHeader       *iphdr = NULL;
        IcmpHeader     *icmphdr = NULL;
        unsigned short  iphdrlen;
        DWORD           tick;
        static   int    icmpcount = 0;    iphdr = (IpHeader *)buf;//为什么强制转换就能转换成ip头呢,
    :这是传来的应该是一个IP报文,而IP报文的前面一部分就是头部,后面才是内容,中间是选项部分。
    // Number of 32-bit words * 4 = bytes
        iphdrlen = iphdr->h_len * 4;IP头中有个头长度/4的数据位(包括选项)
        tick = GetTickCount();取得时间    if ((iphdrlen == MAX_IP_HDR_SIZE) && (!icmpcount))
            DecodeIPOptions(buf, bytes);假如IP是最大的大小或者没ICMPCOUNT    if (bytes  < iphdrlen + ICMP_MIN) 
        {
            printf("Too few bytes from %s\n", 
                inet_ntoa(from->sin_addr));
        }IP包里面没有足够的空间放一个ICMP报文。
        icmphdr = (IcmpHeader*)(buf + iphdrlen);
    IP向后偏移IPHDRLEN就是ICMP报文的地址了。
        if (icmphdr->i_type != ICMP_ECHOREPLY) 
        {
            printf("nonecho type %d recvd\n", icmphdr->i_type);
            return;
        }如果报文不是返回型报文(一共16种)
        // Make sure this is an ICMP reply to something we sent!
        //
        if (icmphdr->i_id != (USHORT)GetCurrentProcessId()) 
        {
            printf("someone else's packet!\n");
            return ;
        }用来判断是不是自己发出去的报文,不然系统无法分出报文的目标,不像TCP那样有地址可以进行标示。
        printf("%d bytes from %s:", bytes, inet_ntoa(from->sin_addr));
        printf(" icmp_seq = %d. ", icmphdr->i_seq);
        printf(" time: %d ms", tick - icmphdr->timestamp);
        printf("\n");    icmpcount++;
        return;
    }
    基本上就是这么回事了。
      

  2.   

    (IpHeader *)没有改变buf的内容
      

  3.   

    不过奇怪的是有两个地方没有return不知道什么原因
        if ((iphdrlen == MAX_IP_HDR_SIZE) && (!icmpcount))
            DecodeIPOptions(buf, bytes);假如IP是最大的大小或者没ICMPCOUNT    if (bytes  < iphdrlen + ICMP_MIN) 
        {
            printf("Too few bytes from %s\n", 
                inet_ntoa(from->sin_addr));
        }特别是这个地方,我想起码应该返回了吧。