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;
阅读(1745) | 评论(1) | 转发(0) |