TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收
在这篇文章中我们看一下server端在接收到异常数据系列时的处理,主要目的是通过wireshark示例对这些异常数据系列的处理有一个直观的认识,感兴趣的自行阅读相关代码和协议,这里不再进行详细介绍
在进行下面的测试前,首先如下设置相关的参数,其中window参数指定了到127.0.0.2的tcp连接的最大接收窗口。
root@Inspiron:/home/******/tcp12# ip route change local 127.0.0.2 dev lo window 40
一、wireshark示例
1、一个包部分数据在rcv_nxt后
如下图所示,client在与server建立连接后,首先发出No4数据包,系列号对应[1,10],下图中text列表示这个TCP数据包中实际传输的数据,No4的len=10,应用层实际传输的数据内容为"0123456789"。接着client又在No6数据包中传输系列号为[6,15]的数据包,传输的内容同样为"0123456789",长度同样为10bytes。
可以看到这里No4和No6两个数据包部分系列号重复,No4数据包系列号[6,10]对应字符串"56789",而No6数据包系列号[6,10]对应字符串"01234"。server端对于No6数据包正常回复了一个ACK报文,Ack=16,也就是说确认了系列号16以前的数据,同时可以看到No7这个ACK确认包还带有一个DSACK块,指示发送端收到了重复报文。
最终server端应用层实际读取了15bytes数据,内容为"012345678956789",可见server端把No6报文系列号[6,10]对应的数据丢弃了,但是保留了系列号[11,15]的内容。

2、一个乱序包完全在接收窗口外
如下图所示,client在与server端建立连接后,首先正常发送No4报文,接着发送乱序报文No6。从No5这个确认包可以看到Ack+Win=51,也就是说从系列号51开始的数据都是接收窗外外部的数据(包括系列号51对应的byte)。No6报文对应的系列号为[51,60]正好完全处于接收窗口外部,因此server端会丢失No6这个数据包。server端应用层最终读取了10bytes的数据,即"0123456789"。

3、一个乱序包部分在接收窗口外
这个示例与上一个不同之处在于No6系列号范围为[46,55],也即这个数据包[46,50]系列号在接收窗口内,而[51,55]在接收窗口外部。
接着看No7,No7通过SACK完整的确认了No6数据包,把落在接收窗口外部的[51,55]系列号也完整确认了,注意这个示例与上面的对比。当乱序包部分系列号落在接收窗口外部的时候,linux会正常完整的接收这个数据包,包括落在接收窗口外部的数据。而当这个数据包完全落在接收窗口外部的时候,linux则不会接收这个数据包。
另外值得注意的是No8-No11四次挥手关闭连接的过程,No8携带了SACK信息,No9则回复了一个ACK,注意No10这个FIN包的起始系列号为11,server端正常的接收了这个数据包,这也就意味着server端会把收到乱序No6报文丢掉,应用层并不能成功读取。

4、快速路径下连续包落在接收窗口外
linux对于接收到的数据包处理流程分为快速路径和慢速路径,在接收到紧急指针、tcp头中的window size发生变化等场景下都会进入慢速处理路径,慢速路径相比快速路径会执行更多检查处理。我们先来看一下快速路径下,连续包落在接收窗口外部的情况。为了不让server端更新接收窗口,我们通过SO_RCVBUF选项固定server端的接收缓存,同时我们通过特定的数据包让server端进入delay ACK模式。执行下面的测试前取消通过路由表设置的window参数。
相关的数据交互如下,No4数据包用来触发server端快速的进入delay ACK模式,server回复完No5这个确认包后就会进入delay ACK模式。关于delay ACK相关内容可以参考前面的文章。同时注意No5报文通告的Win=2,也就是接收窗口只剩余2bytes。
接着我们看到client端发送的No6-No32报文都没有触发server端回复ACK确认包。其中No6报文部分落在接收窗口外部,而No7-No32报文都是完全落在接收窗口外部的数据包。从No34这个确认包可以看到server端对于部分落在接收窗口内部的No6和完全落在接收窗口外部的No7-No32都接收了。而对于No33则没有进行接收,随后在发送No35数据包server端也没有接收。
这里No6-No32能被正常接收的原因是,linux中TCP会预留一定的缓存,当在快速处理模式下时候并不会执行严格的检查,只要新接收的数据包所占用的缓存没有超过预留的缓存就会正常接收。No6-No32都没有超过预留的缓存,因此server端正常接收。但是server端在接收到No34的时候,预留缓存不足,就会直接丢弃这个数据包,并进入quick ACK模式立即回复一个ACK,可以看到No34是一个零窗ACK报文,因此server端也就退出数据包的快速处理模式,随后在收到No35的时候会进入数据包慢速处理流程,执行检查的时候发现此时接收窗口大小为0,No35落在了接收窗口外面,因此同样会直接丢弃这个数据包并立即回复一个ACK确认包。


5、慢速路径下连续包落在接收窗口外
实际上上一次示例No35的处理已经是在慢速路径下处理的了。我们在看另外一个类似的示例。下图示例中No1-No15报文的处理与上面的示例类似,不同的地方在于No16这个数据包的Win发生了更新。server端在收到No16这个数据包的时候,发现No16更新了window size就会退出快速路径的处理进入慢速路径,以执行更复杂的检查和处理。在慢速路径中server端发现No16落在的接收窗口外部,因此直接丢弃这个数据包并进入quick ACK模式立即回复一个No17确认包,回复No17确认包的时候发现Win=0,server端TCP则退出数据包的快速处理模式,在随后接收到新数据包的时候则直接进入慢速路径处理。

6、乱序包内容部分重叠
如下图所示,client依次发送5个数据包,相关TCP交互如下图所示

为了方便对比,我把五个数据包对应的做如下图展示,其中第一行表示系列号比特位,第二行表示server端应用层实际读取的数据流,余下的5行分别表示client依次发送的5个数据包,其中数据包的红色部分表示最终被server端丢弃,数据包的绿色部分表示最终被server端接收。从下图可以看到一旦一个新接收的报文与之前报文重叠的时候,如果是新接收报文的前端发生重叠,那么新接收报文的前端内容会被丢掉,如果是后端重叠,那么之前接收的报文的内容将会被丢掉。

补充说明:
1、linux相关函数数据包接收处理:tcp_rcv_established、tcp_data_queue、tcp_data_queue_ofo
2、慢速路径快速路径等相关函数:tcp_fast_path_check,重点是tp->pred_flags这个标志变量在不同地方的更新
TCP系列36—窗口管理&流控—10、linux下的异常报文系列接收的更多相关文章
- TCP系列27—窗口管理&流控—1、概述
在前面的内容中我们依次介绍了TCP的连接建立和终止过程和TCP的各种重传方式.接着我们在这部分首先关注交互式应用TCP连接相关内容如延迟ACK.Nagle算法.Cork算法等,接着我们引入流控机制(f ...
- TCP系列31—窗口管理&流控—5、TCP流控与滑窗
一.TCP流控 之前我们介绍过TCP是基于窗口的流量控制,在TCP的发送端会维持一个发送窗口,我们假设发送窗口的大小为N比特,网络环回时延为RTT,那么在网络状况良好没有发生拥塞的情况下,发送端每个R ...
- TCP系列35—窗口管理&流控—9、紧急机制
一.概述 我们在最开始介绍TCP头结构的时候,里面有个URG的标志位,还有一个Urgent Pointer的16bits字段.当URG标志位有效的时候,Urgent Poinert用来指示紧急数据的相 ...
- TCP系列32—窗口管理&流控—6、TCP zero windows和persist timer
一.简介 我们之前介绍过,TCP报文中的window size表示发出这个报文的一端准备多少bytes的数据,当TCP的一端一直接收数据,但是应用层没有及时读取的话,数据一直在TCP模块中缓存,最终受 ...
- TCP系列34—窗口管理&流控—8、缓存自动调整
一.概述 我们之前介绍过一种具有大的带宽时延乘积(band-delay product.BDP)的网络,这种网络称为长肥网络(LongFatNetwork,即LFN).我们想象一种简单的场景,假设发送 ...
- TCP系列28—窗口管理&流控—2、延迟ACK(Delayed Acknowledgments)
一.简介 之前的内容中我们多次提到延迟ACK(Delayed Ack),延迟ACK是在RFC1122协议中定义的,协议指出,一个TCP实现应该实现延迟ACK,但是ACK不能被过度延迟,协议给出延迟AC ...
- TCP系列33—窗口管理&流控—7、Silly Window Syndrome(SWS)
一.SWS介绍 前面我们已经通过示例看到如果接收端的应用层一直没有读取数据,那么window size就会慢慢变小最终可能变为0,此时我们假设一种场景,如果应用层读取少量数据(比如十几bytes),接 ...
- TCP系列29—窗口管理&流控—3、Nagle算法
一.Nagle算法概述 之前我们介绍过,有一些交互式应用会传递大量的小包(称呼为tinygrams),这些小包的负载可能只有几个bytes,但是TCP和IP的基本头就有40bytes,如果大量传递这种 ...
- TCP系列30—窗口管理&流控—4、Cork算法
一.Cork算法概述 Cork算法与Nagle算法类似,也有人把Cork算法称呼为super-Nagle.Nagle算法提出的背景是网络因为大量小包小包而导致利用率低下产生网络拥塞,网络发生拥塞的时候 ...
随机推荐
- HTML5中的拖拽与拖放(drag&&drop)
1.drag 当拖动某个元素时,将会依次触发下列事件: 1)dragstart:按下鼠标键并开始移动鼠标时,会触发该事件 2)drag:dragstart触发后,随即便触发drag事件,而且在元素被拖 ...
- python的基本知识
1. python的简介 python的创始⼈人为吉多·范罗苏姆(Guido van Rossum).1989年年的圣诞节期间,吉多· 范罗苏姆为了了在阿姆斯特丹丹打发时间,决⼼心开发⼀个新的脚 ...
- webpack4的react打包错误
因为之前一直用的是脚手架创建项目,第一次自己学习创建webpack打包.loader我是复制别人的. module: { loaders: [ { test: /\.js?$/, exclude: / ...
- hadoop生态搭建(3节点)-08.kafka配置
如果之前没有安装jdk和zookeeper,安装了的请直接跳过 # https://www.oracle.com/technetwork/java/javase/downloads/java-arch ...
- python学习笔记:第5天 基本数据类型之字典
目录 字典的介绍 补充 字典的介绍 字典(dict)是python中唯一的一个映射的数据类型,它是以一对一对的键值对的形式组成的一个容器,在python中字典也是可变的,我们也可以在字典中存放各种类型 ...
- spark ---词频统计(二)
利用python来操作spark的词频统计,现将过程分享如下: 1.新建项目:(这里是在已有的项目中创建的,可单独创建wordcount项目) ①新建txt文件: wordcount.txt (文件内 ...
- ACM1002:A + B Problem II
Problem Description I have a very simple problem for you. Given two integers A and B, your job is to ...
- 20145234黄斐《信息安全系统设计基础》第六周学习总结(Y86模拟器的安装)
Y86模拟器的安装 由于本人的电脑有些问题,在安装的时候忽然断电导致之前的成果都没有截图. 1.安装bison和flex词法分析工具 sudo apt-get install bison flex t ...
- JS日期转换
用js将从后台得到的时间戳(毫秒数)转换为想要的日期格式 得到后台从数据库中拿到的数据我们希望格式是 2016年10月25日 17时37分30秒 或者 2016/10/25 17:37:30 然而我们 ...
- 阿里otter使用问题汇总
最近在使用otter做为和表从库.(100个分表太难查询了) user_00,user_01...user_99 => user_all 1.问题DDL语句不能执行(exception:setl ...