校验和函数小析

今天在写TCP&UDP校验和的函数时,由于误解了TCP&UDP校验和的原理,所以一直计算不正确。

这篇文章可以说讲的非常清晰易懂了。

但是我看到博主最后抓包的情况,我也进行了抓包,我抓的包并没有TCP&UDP伪头部。

然后我以为TCP&UDP伪头部是IP选项而已,有的包有,有的包没有。

我就这样写了算法,然后不正确, 然后我直接抓了一个小包,进行手工的计算。还是不正确。

然后我才在百度上搜索伪首部的知识,得到如下结果:

伪首部(pseudo
header),通常有TCP伪首部和UDP伪首部。在UDP伪首部中,包含32位源IP地址,32位目的IP地址,8位协议,16位UDP长度。通过伪首部的校验,UDP可以确定该数据报是不是发给本机的,通过首部协议字段,UDP可以确认有没有误传。

1.
伪首部并非TCP&UDP数据报中实际的有效成分。伪首部是一个虚拟的数据结构,其中的信息是从数据报所在IP分组头的分组头中提取的,既不向下传送也不向上递交,而仅仅是为计算校验和。这样的校验和,既校验了TCP&UDP用户数据的源端口号和目的端口号以及TCP&UDP用户数据报的数据部分,又检验了IP数据报的源IP地址和目的地址。伪报头保证TCP&UDP数据单元到达正确的目的地址。因此,伪报头中包含IP地址并且作为计算校验和需要考虑的一部分。最终目的端根据伪报头和数据单元计算校验和以验证通信数据在传输过程中没有改变而且到达了正确的目的地址。

2.伪首部,更确切的说是校验和包含的—个96位的伪首标,是个理论上的值,只是理论上它位于TCP&UDP首标的前面。这个伪首标包含了源地址、目的地址、协议和TCP&UDP长度等字段,这使得TCP&UDP能够防止出现路由选择错误的数据段。这些信息由网际协议(IP)承载,通过TCP&UDP网络接口,在IP上运行的TCP&UDP调用参数或者结果中传递。

附:校验和计算方法,以ip首部为例

为了计算一份数据报的IP检验和,首先把检验和字段置为0。然后,对首部中每个16bit进行二进制反码求和(整个首部看成是由一串16bit的字组成),结果存在检验和字段中。当收到一份IP数据报后,同样对首部中每个16bit进行二进制反码的求和。由于接收方在计算过程中包含了发送方存在首部中的检验和,因此,如果首部在传输过程中没有发生任何差错,那么接收方计算的结果应该为全1。如果结果不是全1(即检验和错误),那么IP就丢弃收到的数据报。但是不生成差错报文,由上层去发现丢失的数据报并进行重传。

下面给出一段不错的程序,可以计算ip,tcp,udp的校验和(我不知道是不是内核函数,我在其他地方见到的。)


// Internet Checksum calculation
static uint16_t ip_xsum (uint16_t *buff, int len, uint32_t xsum)
{
// calculate IP checksum for a buffer of bytes
// len is number of 16-bit values
while (len--)
xsum += * buff++; // accumulate 16-bit sum

while (xsum >> 16) // propagate carries for 1‘s complement
xsum = (xsum & 0xFFFF) + (xsum >> 16);

return (uint16_t) xsum;
}

IP成可以这么调用它。

iphdr->check = ~ip_xsum((uint16_t *)iphdr,struct(strcut iphdr) / 2,0);

TCP和UDP可以这么调用它。

l4->check = ~ip_xsum((uint16_t *)&iphdr->saddr,(iphdr->tot_len -
12)/2,htons(iphdr->protocol + l4_size));

iphdr->tot_len - 12 我知道写的很丑,但是能工作就行了。

时间: 2024-08-01 04:55:45

校验和函数小析的相关文章

Poco logger 日志使用小析

Poco logger 日志使用小析 Poco logger 日志使用小析 日志 logger 库选择 Pocologger 架构简析 步骤一 生成消息 步骤二 写入logger 步骤三 导入channel 步骤四 写文件 使用 h file cpp file main 入口函数 备注 拓展 总结 转载请注明本文链接 日志 在软件开发过程中,为了定位软件运行过程中可能出现的错误,一种常用的做法是在潜在的错误位置,设置防御代码,并且将错误代码执行后的错误信息记录下来,以供后续改进代码提供支持. 在

Python之美[从菜鸟到高手]--NotImplemented小析

今天写代码时无意碰到NotImplemented,我一愣,难道是NotImplementedError的胞弟,所以稍微研究了一下. NotImplemented故名思议,就是"未实现",一般是用在一些比较算法中的,如class的__eq__,__lt__等,注意NotImplemented并不是异常,所以不能 使用raise,当没有实现时应该是return NotImplemented. 我们可以看看django中的Field的实现, @total_ordering class Fie

私人定制javascript中函数小知识点

函数的定义 首先在javascript中,函数就是对象,程序可以随意操控它们.比如,可以给它们设置属性,甚至调用它们的方法.函数使用function关键字来定义.它既可以用在函数定义表达式,也可以用在函数声明语句中.函数声明function后面必须要更上函数名称也就是所谓的函数名称标识符.如果是函数表达式函数名称标识符可有可无.这段重点是函数是对象,所以函数表现出来的种种行为你想想成对象,那么很多疑惑可能就恍如昨日初见. 函数调用 4种方式来调用javascript函数: 1.作为函数 就是函数

JavaScript apply函数小案例

//回调函数1 function callback(a,b,c) { alert(a+b+c); } //回调函数2 function callback2(a,b) { alert(a+b); } //这个方法做了一些操作.然后调用回调函数 function doCallback(fn,args) { fn.apply(this, args); } function test() { //动态调用方法.并传递参数 doCallback(callback2,['a','b']); doCallba

字符串函数构析

字符串函数构析 今日参加了一场笔试,刚好程序题问到一道strcpy函数构建,刚好之前看过字符串函数,同时网上文章大部分都是介绍了下函数的用法,缺少了函数的实现,今日就来自己构析下常见的字符串函数,字符串函数位于标准库的头文件string.h中,在使用函数时需引用该文件 strlen 函数原型:size_t strlen(const char *s) 函数功能:返回s的字符串函数(不包含结尾的0) 函数构析:  size_t strlen(const char *s) /*size_t在不同架构下

sql server 常用的函数小汇

摘录些许sqlserver 常用到的一些函数,便于日常学习使用 一.字符转换函数1.ASCII()返回字符表达式最左端字符的ASCII 码值.在ASCII()函数中,纯数字的字符串可不用‘’括起来,但含其它字符的字符串必须用‘’括起来使用,否则会出错.2.CHAR()将ASCII 码转换为字符.如果没有输入0 ~ 255 之间的ASCII 码值,CHAR() 返回NULL .3.LOWER()和UPPER()LOWER()将字符串全部转为小写:UPPER()将字符串全部转为大写.4.STR()把

C++回调函数简析

什么是回调函数? 回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应.   实现机制: ⑴定义一个回调函数: ⑵提供函数实现的一方在初始化的时候,将回调函数的函数指针注册给调用者: ⑶当特定的事件或条件发生的时候,调用者使用函数指针调用回调函数对事件进行处理. 回调函数作用: 因为可以

Python字典的小析(增删改查)

作为Python的初学者,难免会为了一两个小问题找资料,然而一找资料,发现Python关于字典这方面的解析很少,我在此稍稍解析一下字典的用法和含义,若有不足,望大家批评.(在这我直接以代码形式为大家解析) 先来讲讲我对字典的理解吧 简单粗暴,字典就是键值对,而且是无序的,可控的键值对,并且python中字典可以嵌套字典 一.字典的创建 1.传统的文字表达式 a={'name':'Tom','age':20,'job':'Student'} print a >>> {'name':'Tom

函数小练习02

# 写函数,接收n个数字,求这些参数数字的和.(动态传参) # def func(*args): # return sum(args) # print(func(1,2,3,3)) # 读代码,回答:代码中, 打印出来的值a, b, c分别是什么?为什么? # a = 10 # b = 20 # def test5(a, b): # print(a, b)#20 10 # c = test5(b, a) # print(c)#none # 读代码,回答:代码中, 打印出来的值a, b, c分别是