zoukankan      html  css  js  c++  java
  • Network | UDP checksum

    1. 校验和

    ICMP,IP,UDP,TCP报头部分都有checksum(检验和)字段。IP 首部里的校验和只校验首部;ICMP、IGMP、TCP和UDP首部中的校验和校验首部和数据。

    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    |
    +--------+--------+--------+--------+

     

    2. 校验和的计算方法

    以IP首部中的校验和为例。

    1)首先把校验和字段清零;

    2)然后对每 16 位(2 字节)进行二进制反码求和;

    反码求和时,最高位的进位要进到最低位,也就是循环进位。先取反后相加与先相加后取反,得到的结果是一样的!

    所以校验的代码如下:

     1 unsigned short checksum(unsigned short* head, int bytes) {
     2     unsigned long sum = 0;
     3     while (bytes >= 0) {
     4         sum += *head++;
     5         bytes -= sizeof(unsigned short);
     6     }
     7     if (bytes) {
     8         sum += *head;
     9     }
    10     while (sum >> 16) { // 高16位不为0,最多循环两次
    11         sum = (sum >> 16) + (sum & 0xffff); //高16位是进位,进位是加到最低位的。
    12     }
    13     return ~((unsigned short)sum);
    14 }

    【一个负二进制数的反码形式为在原数基础上按位取反,即对应正数的补。对两个反码表示形式的数字做加法,首先需要进行常规的二进制加法,但还需要在和的基础上加上进位。Internet协议IPv4,ICMP,UDP以及TCP都使用同样的16位反码检验和算法。虽然大多数计算机缺少“循环进位”硬件,但是这种额外的复杂性是可以接受的,因为“对于所有位(bit)位置上的错误都是同样敏感的”。 在UDP中,全0表示省略了可选的检验和特性。另外一种表示:FFFF,指示了0的检验和。(在IPv4中,TCP和ICMP都强制性地规定了检验和,而在IPv6中可以省略)。 注意负数的反码只需按位求数值的补就可以得到,符号不需要变动。】 

    3. 校验原理
    同样以IP首部中的校验和为例。接收方进行校验时,也是对每16位(2字节)进行二进制反码求和。接收方计算校验和时的首部与发送方计算校验和时的首部相比,多了一个发送方计算出来的校验和的反码。因此,如果首部在传输过程中没有发生差错,那么接收方计算的结果应该为全0。

    实例:

    IP头:

    1 45 00 00 31
    2 89 F5 00 00
    3 6E 06 00 00(校验字段)
    4 DE B7 45 5D -> 222.183.69.93
    5 C0 A8 00 DC -> 192.168.0.220

    计算:

    1 4500 + 0031 +89F5 + 0000 + 6e06+ 0000 + DEB7 + 455D + C0A8 + 00DC =3 22C4
    2 0003 + 22C4 = 22C7
    3 ~22C7 = DD38 ->即为应填充的校验和

    当接受到IP数据包时,要检查IP头是否正确,则对IP头进行检验,方法同上:

    计算:

    1 4500 + 0031 +89F5 + 0000 + 6E06+ DD38 + DEB7 + 455D + C0A8 + 00DC =3 FFFC
    2 0003 + FFFC = FFFF
    3 ~FFFF = 00000 ->正确

    说明:
    由于IP报文在网络中传输时TTL是在变化的(每经过一个路由器减一),因此在路由器中要对 IP 首部重新校验。这也解释了为什么IP首部里的校验和只校验首部而不校验数据,因为如果数据也校验,那将给路由器增加巨大的负担。因此对数据校验的任务交给上层协议(TCP或UDP)。

  • 相关阅读:
    XX需求分析系统每日进度(二)
    XX需求分析系统每日进度(一)
    周总结(二)
    Hyperleder Fabric chaincode生命周期
    【转】六种学术不端的引用行为
    引导学生,让学生不走神。
    MySQL 的常用引擎
    LeetCode283移动零问题java高效解法
    使用android studio进行springboot项目的开发
    android逆向反编译工具包下载
  • 原文地址:https://www.cnblogs.com/linyx/p/3609043.html
Copyright © 2011-2022 走看看