IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 计算机网络学习笔记——IP Header Checksum(校验和)的计算方法 -> 正文阅读

[网络协议]计算机网络学习笔记——IP Header Checksum(校验和)的计算方法

从TCP/IP协议看到IP数据报,看到Checksum的算法描述,不甚了了。

The checksum field is the 16 bit one’s complement of the one’s complement sum of all 16 bit words in the header. ————RFC791

1、怎么算IP Header Checksum?

百度百科里对校验和的解释提到了:1的补码和(one’s complement sum)就是带循环进位(end round carry)的加法,在最后对累加结果取反码。
其实这里讲得很清楚了,但不完全清楚。因为对1的补码和到底怎么算,理解错了。

  1. 最开始是按照学数电时对反码加法的理解,即正数的反码等于原码,负数的反码由原码的按位(除了符号位保持为1)取反得到。错。
  2. 百科最后有附的程序,感觉第10行代码是迷之取反。按这个思路求的结果也不对。

百科所附C语言程序

  1. 找到一个求IP Header Cheaksum的正确方法
    1. 把划分出所有的16bit数据逐个相加,一旦有进位,就把它加到最低位。
    2. 最后把结果所有位按位取反。
  2. 又找到一个等价的方法:IP数据报首部校验和算法 详细 非代码(接收方检验结果有笔误,但总体写得很棒!)
    1. 所有数据逐个相加(使用32位的int类型)
    2. 把高16位右移16位,再与低16位相加。循环该步,直至结果的二进制表示不超过16位。

2、反码究竟是什么?怎么可以这样用?

可行的方法找到了,可为什么是这样的呢?就像这篇博客里说的那样,这些16bit数据谈不上有正负号,没有什么符号位,一律按位取反,跟加减算数里的用法相去甚远。

首先根据一下表格明确各个概念:

名称英文名称直译名称
反码one’s complement1的补码
补码two’s complement2的补码

然后看一下维基百科对ones’ complement的解释

The ones’ complement of a binary number is the value obtained by inverting all the bits in the binary representation of the number (swapping 0s and 1s). This mathematical operation is primarily of interest in computer science, where it has varying effects depending on how a specific computer represents numbers.
A ones’ complement system or ones’ complement arithmetic is a system in which negative numbers are represented by the inverse of the binary representations of their corresponding positive numbers. In such a system, a number is negated (converted from positive to negative or vice versa) by computing its ones’ complement. An N-bit ones’ complement numeral system can only represent integers in the range ?(2N?1?1) to 2N?1?1 while two’s complement can express ?2N?1 to 2N?1?1. It is one of three common representations for negative integers in microprocessors, along with two’s complement and sign-magnitude.
The ones’ complement binary numeral system is characterized by the bit complement of any integer value being the arithmetic negative of the value. That is, inverting all of the bits of a number (the logical complement) produces the same result as subtracting the value from 0.

第一段黑体处明确指出1补是所有位按位取反,
第二段黑体部分说1补运算系统中负数表示为对应正数的反码。

由此可知,1补就是所有位取反的一个操作,应用在运算中可以方便负数的表示和运算,但这并非其全部用法

3、反码求和为什么循环进位?

反码求和(one’s complement sum):循环进位。先求和再取反,与先取反再求和,结果是一样的。
那反码求和为什么是循环进位呢?
可以查看问题 为什么二进制反码加减要循环进位?为什么补码加减不需要循环进位?下的回答。其中有分类讨论,讲得非常棒!
最后也猜了下Checksum使用1补的原因。

4、接收端怎么检验,正常结果应该是什么?

接收端收到IP数据报的时候也这么算。
因为Checksum存了其他数据的和的反码(Checksum初始化为0x0000,虽然参加了运算,但跟没参加一样),其他数据之和加上本身的反码,就是0xFFFF,即-0,再取反就是0x0000,即+0
(补充:反码表示负数时,有两个零,补码只有一个零,可以比反码多表示一个负数)

5、Java代码简单实现

java代码如下:

package cn.it.test;

public class CheckSum {
    public static void main(String[] args) {
        int[] msg = {0x9C1A, 0xDA88, 0xAD35, 0x0000};
        System.out.println(checkSum(msg));
    }

    /**
     * IP Header Checksum
     * @param msg 数组中的每一个数都是16bit的
     * @return 返回16进制的字符串
     */
    public static String checkSum(int[] msg) {
    	// one's complement sum 带循环进位的加法
        int sum = 0;
        for (int m : msg) {
            sum += m;
            if (sum > 0xFFFF) {
                sum &= 0xFFFF;
                ++sum;
            }
        }
		
		// one's complement 每一位都按位取反
        sum = ~sum;
        sum &= 0xFFFF;

        return String.format("0x%04x",sum);
    }
}

6、补充简洁的解释

后来查1补的用法时,看到这个回答,非常简洁。

一个例子就是求校验和(Checksum) 通俗一点来讲是:

  1. 先是 one’s complement sum,将data按16位分组,所有组相加,再将进位值加到结果的末位。
  2. 再是 one’s complement,结果取反码。

7、总结

  1. 会求Checksum了
  2. 打破了之前对反码的刻板认识
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-09 17:42:02  更:2021-07-09 17:42:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 14:31:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码