TCP/UDP的checksum校检算法实现,亲测与wireshark一致
程序员文章站
2022-07-10 18:39:01
...
typedef unsigned short u_short;
typedef unsigned int u_int;
u_short swapI16(u_short v)
{
return ((v & 0x00FF) << 8) |
((v & 0xFF00) >> 8);
}
//1.UDP校检的数据有三块,伪头部(12Bytes)+UDP头(8Bytes)+数据
//2.伪头部包括,IP源地址+IP目的地址+mbz(0x0)+协议类型(UDP:17,TCP:6)+UDP长度
// 长度为4+4+1+1+2=12 Bytes
//3.UDP头包括,源端口+目的端口+UDP长度+checksum
// 长度为2+2+2+2=8 Bytes
//4.注意:
// a)伪头部中UDP长度为时间UDP头+数据的长度,UDP头部中UDP长度为0x0000
// b)如果数据长度不是2的整数倍,则必须在最后补一个字节数据,即padding
u_int udp_checksum(void *input, int len)
{
u_short* tmp = (u_short*)input;
u_int sum = 0;
for (int i=0; i<len/2; i++) {
sum += swapI16(*(tmp+i));
}
if (len % 2 == 1) {
sum += (*((unsigned char*)input+len-1) << 8);
}
if (sum > 0xFFFF) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
u_short ret = sum;
return swapI16(~ret);
}
//1.ip校检只校验IP头20字节
//2.ip校检字段必须为0
u_int ip_checksum(void *input, int len)
{
if (len != 20) return 0;
//ip校检置0
memset((char*)input+10, 0, 2);
u_short* tmp = (u_short*)input;
u_int sum = 0;
for (int i=0; i<len/2; i++) {
sum += swapI16(*(tmp+i));
}
if (sum > 0xFFFF) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
u_short ret = sum;
return swapI16(~ret);
}
上一篇: Java随机产生月份
下一篇: checksum 算法