Archive

Posts Tagged ‘C’

关于checksum

October 15th, 2008 frankyue No comments

最近一段时间很忙没来写东西了,发下最近写的一个东西,一个UDP的CHECKSUM(校验和)。

在网络传送的数据包为了保证传送正确都含有效验字段,IP、arp、tcp等每个数据段都有自己的效验和

刚开始找来个现成的IP数据包的校验和,不过后来才知道UDP和IP的校验和还有差别,所有又重新来

UDP报文的头由 发送端端口(2字节),目标端口(2字节),UDP包长度(2字节),校验和(2字节)4部分组成。
校验和的值由伪IP头,UDP头和UDP数据三部分的字串以16bit作单位进行相加后取反码(one’s complement )得到。若数据长度为基数,则最后补一个字节的0。

老师要求都用C语言写,古老的语言阿,都N年没用了,不过嵌入式的东西都用他来完成,虽然我还没接触到嵌入式的东西,用了些之前从没用过的unsigned short,取反等操作,都是接触底层的东西按照网上了解的算法得出如下:

#include
#define INDEXUDPLANG 12
void ChecksumForudp(unsigned short *str1,unsigned short *str2,int len)
{
unsigned short *sbuf;
int i;
unsigned int hi=0, lo=0, hicarry, locarry;

sbuf = (unsigned short *) str1;

for (i = 0 ; i < len ; i += 2)
{
if( i != INDEXUDPLANG )
{
if( i != len-2)
{
hi += sbuf[i];
lo += sbuf[i+1];
}
else
{
hi += sbuf[i];
lo += sbuf[i+1];
}
}
else
{
hi +=sbuf[i]+sbuf[i];//加两次包长
lo +=sbuf[i+1]+sbuf[i+1];//加两次包长
}
}

lo += 0×11; //加UDP协议值0×0011

hicarry = hi >> 8; //提取进位
locarry = lo >> 8;

while (hicarry || locarry)
{ //将进位循环加回
hi = (hi & 0xFF) + locarry;
lo = (lo & 0xFF) + hicarry;
hicarry = hi >> 8;
locarry = lo >> 8;

}

sbuf[INDEXUDPLANG]= (~hi) & 0xff; //将checksum高位放入
sbuf[INDEXUDPLANG+1]= (~lo) & 0xff; //将checksum低位放入

str2 = str1;
}
int main()
{
//unsigned short str[]= {0×0a,0×99,0×35,0×0f,0×0a,0×00,0×00,0xac,0×20,0xdb,0×23,0xf1,0×00,0×0b,0×00,0×00,0×18,0×00,0×23};
unsigned short str[]= {0×0a,0×99,0×35,0×0f,0×0a,0×00,0×00,0xac,0×20,0xdb,0×23,0xf1,0×00,0×7b,0×00,0×00,0×0a,0×00,0×21,0×12
,0×01,0×10,0×13,0×58,0×04,0×80,0×83,0xd4,0×60,0×04,0×81,0×83,0xd4,0×60,0×02,0×82,0×00,0×02,0×83,0×05,0×02,0×84,0×01,0×80
,0×80,0×83,0×99,0×81,0xea,0xa9};
unsigned short *str1,*str2;
str1=str;
int i = 0;
ChecksumForudp(str1,str2,50);

printf(“%x\n”,str1[12]);
printf(“%x\n”,str1[13]);
printf(“ANSWER IS 35B8!\n”);
}

还有个BUG,就是UDP包最长为65535,在进行加法hi和lo是会不会超过int 长度,在得到hicarry和locarry会不会使数据丢失,总想不明白会不会,自己数学太差了!我再琢磨琢磨!

得去装个代码查看插件,这里发出来的格式都变了郁闷

Categories: C Tags: