今天复习计网的时候看到了UDP头部有差错校验,其中的checksum算法没理的太清楚,索性写一篇博客,顺便回顾一下其他的。

校验和覆盖的内容:

IP校验和:IP首部。
ICMP校验和:ICMP首部+ICMP数据;
UDP、TCP校验和:首部+数据+12个字节伪首部(源IP地址、目的IP地址、协议、TCP/UDP包长)。

计算校验和的步骤:

[1]把校验和字段设置为0。
[2]把需要校验的数据看成以16位为单位的数字组成,依次进行二进制反码求和。
[3]把得到的结果存入校验和字段中。
另外UDP、TCP数据报的长度可以为奇数字节,因为计算时是16位为单位,所以此时计算校验和时需要在最后增加一个填充字节0(只是计算校验和用,不发送出去)。

接收端校验校验和步骤:

把需要校验的内容(包括校验和字段)看成以16位为单位的数字,依次进行二进制反码求和,如果结果是0表示正确,否则表示错误。

二进制反码求和步骤:

[1]二进制反码求和,就是先把这两个数取反,然后求和,如果最高位有进位,则向低位进1。

[2]另外,先取反后相加与先相加后取反,得到的结果是一样的。因此实现代码都是先相加,最后再取反。

下面我们来写个栗子

以4bit(计算方便一点,和16bit是一样的)做检验和来验证。

假设原始数据为 1100 1010 | 0000(校验位)(初始化为0000)
那么把他们按照4bit一组进行按位取反相加。 1100 取反0011 , 1010 取反是0101,校验位的计算就是 0011加上0101 是1000,填入到校验位上
于是发送的数据就是
1100 1010 | 1000
收到数据后同样进行按位取反相加。0011+0101+0111 =1111;全为1表示正确 。 等于是 自己加上自己的取反, 那么 结果肯定应该是全1 。如果传输正确的话。

更多思考

至于我一直百思不解的 那个数据报里面那么多数据加起来肯定是每个位都是1这个问题
我们来考虑一种极端情况:
0000 0000
它的校验和是1111
如果最高位需要进位 那么补到最低位上(回卷)
发送过去的 0000 0000 1111 加起来就是1111
当然 如果后面再加个不是0000 比如1010
1010按位取反是0101
加上去那么校验和是0101
发送过去的数据是0000 0000 1010 | 0101
加起来的和还是1111
感觉checksum这个算法设计的太妙了

在实际使用过程中 先把需要校验的数据加起来 然后取反码,这样的效果是一样的,而且还减少了计算量

NOTE:
这里是按位取反 不是反码

原码 反码 补码

在学习原码, 反码和补码之前, 需要先了解机器数和真值的概念.

机器数和真值

机器数

一个数在计算机中的二进制表示形式, 叫做这个数的机器数。机器数是带符号的,在计算机用一个数的最高位存放符号, 正数为0, 负数为1.

比如,十进制中的数 +3 ,计算机字长为8位,转换成二进制就是00000011。如果是 -3 ,就是 10000011 。

那么,这里的 00000011 和 10000011 就是机器数。

真值

因为第一位是符号位,所以机器数的形式值就不等于真正的数值。例如上面的有符号数 10000011,其最高位1代表负,其真正数值是 -3 而不是形式值131(10000011转换成十进制等于131)。所以,为区别起见,将带符号位的机器数对应的真正数值称为机器数的真值。

例:0000 0001的真值 = +000 0001 = +1,1000 0001的真值 = –000 0001 = –1

原码, 反码, 补码的基础概念和计算方法.

在探求为何机器要使用补码之前, 让我们先了解原码, 反码和补码的概念.对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.

原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

[+1]原 = 0000 0001

[-1]原 = 1000 0001

第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:

[1111 1111 , 0111 1111]

[-127 , 127]

原码是人脑最容易理解和计算的表示方式.

反码

反码的表示方法是:

正数的反码是其本身

负数的反码是在其原码的基础上, 符号位不变,其余各个位取反.

[+1] = [00000001]原 = [00000001]反

[-1] = [10000001]原 = [11111110]反

可见如果一个反码表示的是负数, 人脑无法直观的看出来它的数值. 通常要将其转换成原码再计算.

补码

补码的表示方法是:

正数的补码就是其本身

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [00000001]原 = [00000001]反 = [00000001]补

[-1] = [10000001]原 = [11111110]反 = [11111111]补

对于负数, 补码表示方式也是人脑无法直观看出其数值的. 通常也需要转换成原码在计算其数值.

为何要使用原码, 反码和补码

在开始深入学习前, 我的学习建议是先"死记硬背"上面的原码, 反码和补码的表示方式以及计算方法.

现在我们知道了计算机可以有三种编码方式表示一个数. 对于正数因为三种编码方式的结果都相同:

[+1] = [00000001]原 = [00000001]反 = [00000001]补

所以不需要过多解释. 但是对于负数:

[-1] = [10000001]原 = [11111110]反 = [11111111]补

可见原码, 反码和补码是完全不同的. 既然原码才是被人脑直接识别并用于计算表示方式, 为何还会有反码和补码呢?

首先, 因为人脑可以知道第一位是符号位, 在计算的时候我们会根据符号位, 选择对真值区域的加减. (真值的概念在本文最开头). 但是对于计算机, 加减乘数已经是最基础的运算, 要设计的尽量简单. 计算机辨别"符号位"显然会让计算机的基础电路设计变得十分复杂! 于是人们想出了将符号位也参与运算的方法. 我们知道, 根据运算法则减去一个正数等于加上一个负数, 即: 1-1 = 1 + (-1) = 0 , 所以机器可以只有加法而没有减法, 这样计算机运算的设计就更简单了.

于是人们开始探索 将符号位参与运算, 并且只保留加法的方法. 首先来看原码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

为了解决原码做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

1 - 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原= [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0

发现用反码计算减法, 结果的真值部分是正确的. 而唯一的问题其实就出现在"0"这个特殊的数值上. 虽然人们理解上+0和-0是一样的, 但是0带符号是没有任何意义的. 而且会有[0000 0000]原和[1000 0000]原两个编码表示0.

于是补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128. 但是注意因为实际上是使用以前的-0的补码来表示-128, 所以-128并没有原码和反码表示.(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

原码, 反码, 补码 再深入

计算机巧妙地把符号位参与运算, 并且将减法变成了加法, 背后蕴含了怎样的数学原理呢?

将钟表想象成是一个1位的12进制数. 如果当前时间是6点, 我希望将时间设置成4点, 需要怎么做呢?我们可以:

  1. 往回拨2个小时: 6 - 2 = 4

  2. 往前拨10个小时: (6 + 10) mod 12 = 4

  3. 往前拨10+12=22个小时: (6+22) mod 12 =4

2,3方法中的mod是指取模操作, 16 mod 12 =4 即用16除以12后的余数是4.

所以钟表往回拨(减法)的结果可以用往前拨(加法)替代!

现在的焦点就落在了如何用一个正数, 来替代一个负数. 上面的例子我们能感觉出来一些端倪, 发现一些规律. 但是数学是严谨的. 不能靠感觉.

首先介绍一个数学中相关的概念: 同余

同余的概念
两个整数a,b,若它们除以整数m所得的余数相等,则称a,b对于模m同余

记作 a ≡ b (mod m)

读作 a 与 b 关于模 m 同余。

举例说明:

4 mod 12 = 4

16 mod 12 = 4

28 mod 12 = 4

所以4, 16, 28关于模 12 同余.

负数取模
正数进行mod运算是很简单的. 但是负数呢?

下面是关于mod运算的数学定义:

clip_image001

上面是截图, "取下界"符号找不到如何输入(word中粘贴过来后乱码). 下面是使用"L"和"J"替换上图的"取下界"符号:

x mod y = x - y L x / y J

上面公式的意思是:

x mod y等于 x 减去 y 乘上 x与y的商的下界.

以 -3 mod 2 举例:

-3 mod 2

= -3 - 2xL -3/2 J

= -3 - 2xL-1.5J

= -3 - 2x(-2)

= -3 + 4 = 1

所以:

(-2) mod 12 = 12-2=10

(-4) mod 12 = 12-4 = 8

(-5) mod 12 = 12 - 5 = 7

引用

本文引用了以下文章的部分内容
https://blog.csdn.net/zl10086111/article/details/80907428
https://www.cnblogs.com/ne-liqian/p/9804214.html
https://www.cnblogs.com/seasonal/p/10343642.html

关于checksum校验和算法相关推荐

  1. 网际校验和算法(Internet CheckSum)

    网际校验和算法 反码算数运算: 两个数进行二进制反码求和的运算很简单.它的规则是从低位到高位逐列进行计算.0和0相加是0,0和1相加是1,1和1相加是0但要产生一个进位1,加到下一列.如果最高位相加后 ...

  2. TCP/IP 校验和算法简介

    1. 前言 校验和计算是NAT功能和内容修改功能的基本功,这些操作进行后都需要修改数据头中的校验和. 2. 16位校验和计算 2.1 基本原理 IP/ICMP/IGMP/TCP/UDP等协议的校验和算 ...

  3. 计算机网络首部检验和怎么算,计算机网络校验和算法

    校验和算法 经常看计算机网络相关的书时,每次看到关于IP或者是UDP报头校验和时,都是一笑而过,以为相当简单的东西,不就是16bit数据的相加吗!最近在学习Ping命令的源码时,看到里面有关于校验和的 ...

  4. checksum命令 linux_数字签名及 Checksum 校验和

    数字签名及验签 一般情况,为了证明文件或信件从源端通过网络传输到目的端未被人为篡改,通常采用数字签名的技术. 通过如下简单几步实现数据签名及验签. 发送方数字签名过程: 发送者通过散列函数将带发送的数 ...

  5. Checksum 校验和

    一 校验数据的一般算法比较 都是通过对数据进行校验产生一个校验值,用来校验数据完整性. 不同点: 算法不同: CRC采用多项式除法,MD5和SHA1使用的是替换.轮转等方法: 校验值的长度不同: CR ...

  6. c语言 checksum,容易被忽视的IP报头中的Checksum校验和

    看计算机网络相关的书,每次看到IP或者UDP报头校验和时,都一瞥而过,以为相当简单.可是今天一看真傻眼了,怎么算的,为什么用反码不用补码还真不知道怎么回事. 算法的C语言实现: unsignedsho ...

  7. 使用md5校验和算法保护文件

    近日要用到文件校验算法,查看了一下相关资料,得到以下理论与实践经验. 一.理论部分: 1.预备知识 1.1什么是数据校验 通俗的说,就是为保证数据的完整性,用一种指定的算法对原始数据计算出的一个校验值 ...

  8. SQL SERVER数据页checksum校验算法

    在SQL SERVER2005以上版本中,数据页默认开启checksum,标识为m_flagBits & 0x200 == True,其值m_tornBits位于页头0x3C,4字节. 其算法 ...

  9. IP头TCP头的checksum校验和计算

    校验和就是数据位按位相加之后取反所得,验证校验和的时候把数据位按位相加再加上校验和如果等于零则表示验证通过. 如:数据位相加为1010, 那么校验和为0101,验证时1010+0101=0,验证通过. ...

最新文章

  1. vbscript调用WMI一键式式发布网站
  2. oracle数据库的高可用r,Oracle高可用之dataguard
  3. Android之tint图片着色器
  4. php获取post全部数据,PHP获取POST数据的几种方法汇总_PHP教程
  5. 福州联通与市政府携手 共筑新型智慧城市
  6. 【CentOS 7LAMP架构4】,PHP5和PHP7的安装和配置#171219
  7. Daily Scrum02 12.03
  8. git 提示error setting certificate verify locations 解决方案
  9. GIT更新一其中一个提交版本
  10. Windows查看计算机服务监听的端口号
  11. 从奥卡姆剃刀定律再看决策树
  12. 电源的输出纹波噪声究竟该取多少才合适?
  13. 艾司博讯:拼多多一件代发怎么发货
  14. 信用卡不激活到底会怎样?会有哪些负面影响呢?
  15. Ios5(三)屏幕的旋转和大小设置;
  16. 北京第二外国语学院本科毕业论文答辩PPT模板
  17. 真正福建电信笔试题(专业对口请进)(转载)
  18. XSS(Cross-site Script,跨站脚本)漏洞笔记
  19. 编写Java程序,模拟教练员和运动员出国比赛场景,其中运动员包括乒乓球运动员和篮球运动员。教练员包括乒乓球教练和篮球教练。为了方便出国交流,根乒乓球相关的人员都需要学习英语。
  20. 意念控制助听器,想听什么听什么

热门文章

  1. 《Unity3D-鱼的方向 鱼的游动 控制代码》
  2. dreamweaver cs4 css汉化补丁,dreamweaver cs4官方版
  3. C语言数组练习-摘苹果
  4. Java面试通关要点汇总集(基础篇之基本功,非原作者)
  5. Spring Boot 容器镜像分层构建
  6. 东华大学专业英语 词汇学习
  7. [转贴]郎恒《齐天大圣》Rap 搞笑!
  8. 【学习笔记】Windows格式文档转换成Unix格式
  9. DNS中有哪些值得学习的优秀设计
  10. python听歌识曲爬虫_【python爬虫】 爬云音乐我和xxx共同听过的歌曲