Chinaunix首页 | 论坛 | 博客
  • 博客访问: 516149
  • 博文数量: 118
  • 博客积分: 10028
  • 博客等级: 上将
  • 技术积分: 1820
  • 用 户 组: 普通用户
  • 注册时间: 2007-11-07 18:46
文章分类

全部博文(118)

文章存档

2009年(12)

2008年(106)

我的朋友

分类: C/C++

2008-08-23 10:35:08



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;
阅读(1719) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-07-22 09:06:38

解释的很好,谢谢啦!