现在的位置: 首页 > 综合 > 正文

关于IP首部校验和计算的解答

2013年06月06日 ⁄ 综合 ⁄ 共 1253字 ⁄ 字号 评论关闭
 IP效验和计算的代码:

unsigned short check_sum(unsigned short *addr,int len)
{
    register int nleft=len;
    register int sum=0;
    register short *w=addr;
    short answer=0;
    while(nleft>1)
    {
        sum+=*w++;
        nleft-=2;
    }
    if(nleft==1)
    {
        *(unsigned char *)(&answer)=*(unsigned char *)w;
        sum+=answer;
    }
    sum=(sum>>16)+(sum&0xffff);
    sum+=(sum>>16);
    answer=~sum;
    return(answer);
}

.....
上面太长,我只想说最后的几句

    sum=(sum>>16)+(sum&0xffff);
    sum+=(sum>>16);
    answer=~sum;

上一个程序已经看到,sum是一个32位整形,而我们要的效验和是16位的,所以必须要把前面16位和计算得到

的sum再加工,得到最后的answer,这个加工过程看似简单,但我开始是没搞清楚的,后来经过CUBBS上的

兄弟们帮忙,搞清楚了,所以在这里贴一下~~

1).sum=(sum>>16)+(sum&0xffff);
   这句是“把sum的高16位加到低16位”,具体分析:(sum>>16)是将高16位移位到低16位,

(记住此时sum值是没有变的哦~),此时这个括号的值就是sum的高16位的值(但在低16位位置上);

(sum&0xffff)是取出sum的低16位,按位与应该都能理解(此时sum的值依然是没变的哦~),

最终,“+”前的高16位值和“+”后的低16位值相加(虽然一个是高16位值一个是低16位值,

但现在它们的位置都在低16位,所以相加)

得到新的sum.
   可以把句子"复杂化":
       sum1=sum>>16;
       sum2=sum&0xffff;
       sum=sum1+sum2;
2).sum+=(sum>>16);
    (这一句差点没想出来,嘿嘿)这句的意思是:把sum的进位加到低16位。效验和是要加进位的,在上一步中

sum已经变化了,高低16位都已经加到低16位,但不要忽略了可能的进位,因为是多个16位和,所以进位是

常有的事,这就是这一句的作用.
3).answer=~sum;
     answer是2B的(不是骂它哈),所以4B的sum取反,再赋值给answer,answer取到低16位。
GAME OVER

说简单不简单,说复杂不复杂,需要注意几个地方:
      1.sum值在计算的第一步中,位移和按位与sum的值是始终不变的;
      2.不能忽略进位;
      3.怎样把32位的变量的值弄成2B;

抱歉!评论已关闭.