IP/TCP/UDP校验和的计算
1. 校验和ICMP,IP,UDP,TCP报头部分都有checksum(检验和)字段。IP 首部里的校验和只校验首部;ICMP、IGMP、TCP和UDP首部中的校验和校验首部和数据。1)IP头长度为20字节,IP校验和只对IP协议头进行计算。UDP协议头为8字节:0 7 8 15 16 23 24 31+--------+--------
1. 校验和
ICMP,IP,UDP,TCP报头部分都有checksum(检验和)字段。IP 首部里的校验和只校验首部;ICMP、IGMP、TCP和UDP首部中的校验和校验首部和数据。
1)IP头长度为20字节,IP校验和只对IP协议头进行计算。
UDP协议头为8字节:
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| source port |destination port |
+--------+--------+--------+--------+
| UDP length | UDP checksum |
+--------+--------+--------+--------+
TCP协议头为20到60字节:
UDP和TCP的校验和不仅要对整个IP协议负载(包括UDP/TCP协议头和UDP/TCP协议负载)进行计算,还要先对一个伪协议头进行计算:先要填充伪首部各个字段,然后再将UDP/TCP报头及之后的数据附加到伪首部的后面,再对位首部使用校验和计算,所得到的值才是UDP/TCP报头部分的校验和。
伪首部结构如下:
0 7 8 15 16 23 24 31
+--------+--------+--------+--------+
| source address |
+--------+--------+--------+--------+
| destination address |
+--------+--------+--------+--------+
| zero | proto | udp/tcp len |
+--------+--------+--------+--------+
伪首部可以用如下的结构体表示:
struct pseudo_head {
uint32_t saddr; //源IP地址
uint32_t daddr; //目的IP地址
char zero; //置空(0)
char proto; //协议类型
unsigned short len; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度,单位:字节)
};
2. 校验和的计算方法
以IP首部中的校验和为例。
1)首先把校验和字段清零;
2)然后对每 16 位(2 字节)进行二进制反码求和;
这里说的反码求和,不是说先对每 16 位求反码然后求和,而是说把每 16 位当做反码求和;
反码求和时,最高位的进位要进到最低位,也就是循环进位。
求校验和的C代码实现:
short checksum(short *buffer, int size)
{
unsigned long cksum=0;
while(size >1)
{
cksum+=*buffer++;
size -=sizeof(short);
}
if(size )
{
cksum += *(char*)buffer;
}
cksum = (cksum >> 16) + (cksum & 0xffff);
cksum += (cksum >>16);
return (short)(~cksum);
}
3. 校验原理
同样以IP首部中的校验和为例。接收方进行校验时,也是对每16位(2字节)进行二进制反码求和。接收方计算校验和时的首部与发送方计算校验和时的首部相比,多了一个发送方计算出来的校验和的反码。因此,如果首部在传输过程中没有发生差错,那么接收方计算的结果应该为全一。
说明:
由于IP报文在网络中传输时TTL是在变化的(每经过一个路由器减一),因此在路由器中要对 IP 首部重新校验。这也解释了为什么IP首部里的校验和只校验首部而不校验数据,因为如果数据也校验,那将给路由器增加巨大的负担。因此对数据校验的任务交给上层协议(TCP或UDP)。
=====================end========================
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)