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)。

  • 相关阅读:
    【今日CV 视觉论文速览】 19 Nov 2018
    【numpy求和】numpy.sum()求和
    【今日CV 视觉论文速览】16 Nov 2018
    【今日CV 视觉论文速览】15 Nov 2018
    poj 2454 Jersey Politics 随机化
    poj 3318 Matrix Multiplication 随机化算法
    hdu 3400 Line belt 三分法
    poj 3301 Texas Trip 三分法
    poj 2976 Dropping tests 0/1分数规划
    poj 3440 Coin Toss 概率问题
  • 原文地址:https://www.cnblogs.com/linyx/p/3609043.html
Copyright © 2011-2022 走看看