c语言 checksum,容易被忽视的IP报头中的Checksum校验和
看计算机网络相关的书,每次看到IP或者UDP报头校验和时,都一瞥而过,以为相当简单。可是今天一看真傻眼了,怎么算的,为什么用反码不用补码还真不知道怎么回事。
算法的C语言实现:
unsignedshortcsum(unsignedchar *addr,intcount)
{
/* Compute Internet Checksum for "count" bytes
* beginning at location "addr".
*/
register long sum = 0;
while( count > 1 ) {
/* This is the inner loop */
sum += * (unsigned short) addr++;
count -= 2;
}
/* Add left-over byte, if any */
if( count > 0 )
sum += * (unsigned char *) addr;
/* Fold 32-bit sum to 16 bits */
while (sum>>16)
sum = (sum & 0xffff) + (sum >> 16);
checksum = ~sum;
return checksum;
}
计算校验和的算法思路:
1. 将原Checksum位置全部置0,把报头中每16bit作为一组,当成无符号数相加得到sum,若报头字节数为单数,则最后一个字节直接当8bit无符号数加到前面的sum上去。
2. 对sum右移16位,并与原sum的低16位相加,得到结果重新赋给sum。
3. 直到sum的高16位为0时,再将sum取反(反码),返回sum值作为Checksum。
接收端校验过程:
接收到的结果再进行一次上述计算,得到返回的值应该为0。否则,报头在传输过程中出错。
解释1:B + ~B = 2^16 - 1(B 为WORD),算法最后返回的是反码(反码求和又叫1的补码(one'scomplement),而2的补码就是我们通常说的补码求和了)。所以接收端收到数据报后得到的校验和为B + ~B(开始校验和占用的两个字节为0,现在更过发送端的校验后得到~B) = 2^16 - 1(B 为WORD),返回校验和的反码所以就检查校验和是否为0即可。
那么为什么用反码而不用补码呢?
a.不依赖系统是大端还是小端。即无论你是发送方计算或者接收方检查校验和时,都不需要调用htons 或者 ntohs,直接通过上面第2节的算法就可以得到正确的结果。这个问题你可以自己举个例子,用反码求和时,交换16位数的字节顺序,得到的结果相同,只是字节顺序相应地也交换了;而如果使用原码或者补码求和,得到的结果可能就不相同!比如补码计算:0xff02 + 0x00ff 和0x02ff + 0xff00结果是不相同的, 但是对于反码来说只是序列不同结果是相同的。
b.计算和验证校验和比较简单,快速。说实话,这个没怎么看明白,感觉在校验和计算方面,原码或者补码求和反而更简单一些(从C语言角度),在校验和验证上面,通过一样的算法判断结果是否为全0,确实要方便一些,所以可能从综合考虑确实反码求和要简便一些。另外,IP报文在传输过程中,路由器经常只修改TTL字段(减1),此时路由器转发该报文时可以直接增加它的校验和,而不需要对IP整个首部进行重新计算。
c语言 checksum,容易被忽视的IP报头中的Checksum校验和相关推荐
- 如何计算IP报头的checksum
如果你研究过TCP/IP协议,那么你肯定知道IP报头中的checksum字段,或许你还曾经为如何计算这个字段的值所困扰,本文我们将讨论checksum的概念,并详细介绍IP报头中的checksum是如 ...
- 《深入浅出DPDK》读书笔记(十):硬件加速与功能卸载(VLAN、IEEE1588、IP TCP/UDP/SCTP checksum、Tunnel)
Table of Contents 109.硬件卸载简介 110.网卡硬件卸载功能 111.DPDK软件接口 接收侧: 发送侧: 112.硬件与软件功能实现 113.VLAN硬件卸载 1. 收包时VL ...
- TCP/IP协议中分包与重组原理介绍、分片偏移量的计算方法、IPv4报文格式
目录 一.什么是IP分片 二,为什么要进行IP分片 三.IP分片原理及分析 标志字段的作用 下面是标志位在IP首部中的格式以及各个标志的意义: TTL Protocol 协议号 分片包文示例: 分片偏 ...
- 已知子网掩码如何计算IP地址中的主机位
原文链接:https://zhidao.baidu.com/question/214865175.html 某A类地址上的子网掩码是255.192.0.0,那么该IP地址中主机有多少位? 255.19 ...
- R语言使用basename函数获取数据链接地址中的文件名称(removes all of the path up to and including the last path separator )
R语言使用basename函数获取数据链接地址中的文件名称(removes all of the path up to and including the last path separator (i ...
- R语言data.table导入数据实战:data.table中编写函数并使用SD数据对象
R语言data.table导入数据实战:data.table中编写函数并使用SD数据对象 目录 R语言data.table导入数据实战:data.table中编写函数并使用SD数据对象 #data.t ...
- R语言ggplot2可视化:通过在element_text函数中设置ifelse判断条件自定义标签文本的显示格式:例如、粗体、斜体等
R语言ggplot2可视化:通过在element_text函数中设置ifelse判断条件自定义标签文本的显示格式:例如.粗体.斜体等 目录
- R语言plotly可视化:plotly可视化在散点图中添加误差条(Scatterplot with Error Bars with plotly in R)
R语言plotly可视化:plotly可视化在散点图中添加误差条(Scatterplot with Error Bars with plotly in R) 目录 R语言
- R语言可视化密度图并在密度图中嵌入图例信息、使用geomtextpath包的geom_textdensity函数,将图例(legend)信息嵌入到密度图中
R语言可视化密度图并在密度图中嵌入图例信息.使用geomtextpath包的geom_textdensity函数,将图例(legend)信息嵌入到密度图中(Density plot with dire ...
最新文章
- 【带你玩转主题模型Topic Model】—— 之 利用sklearn 实现Latetnt Dirichlet Allocation(LDA)主题模型
- 拥抱iPhone,拥抱软件开发的未来
- python中内存管理机制一共分为多少层_python 内存管理机制
- 【自定义注解使用】增加service层方法访问日志
- DRF_APIView之认证、授权配置
- QT 4.8.5支持电容触摸屏 和 鼠标
- STL源码剖析 关联式容器 树 红黑树、二叉搜索树、平衡二叉搜索树
- TensorFlow 2.0 - tf.distribute 分布式训练
- (转载)python调用shell命令之os 、commands、subprocess
- Netty工作笔记0084---通过自定义协议解决粘包拆包问题2
- 夜上海音乐播放器 v 1.0
- pip和pip3 换源
- gif转换成jpg,这个方法很简单
- 使用Xcode创建第一个App
- @Resource详解
- 有个空间,名叫 Gamma
- ajax 更新局部视图,使用Ajax局部更新Razor页面的实例代码
- 汇智网mysql_MySQL 入门
- C++STL算法 search你是我的半截的诗
- 利用DOCX文档远程模板注入执行宏代码