tcpack---1简述
TCP重传机制
TCP要保证所有的数据包都可以到达,所以,必需要有重传机制。
超时重传机制
一种是不回ack,死等3,当发送方发现收不到3的ack超时后,会重传3。一旦接收方收到3后,会ack 回 4——意味着3和4都收到了。
但是,这种方式会有比较严重的问题,那就是因为要死等3,所以会导致4和5即便已经收到了,而发送方也完全不知道发生了什么事,因为没有收到Ack,所以,发送方可能会悲观地认为也丢了,所以有可能也会导致4和5的重传。
对此有两种选择:
- 一种是仅重传timeout的包。也就是第3份数据。
- 另一种是重传timeout后所有的数据,也就是第3,4,5这三份数据。
这两种方式有好也有不好。第一种会节省带宽,但是慢,第二种会快一点,但是会浪费带宽,也可能会有无用功。但总体来说都不好。因为都在等timeout,timeout可能会很长(在下篇会说TCP是怎么动态地计算出timeout的)
快速重传机制
于是,TCP引入了一种叫Fast Retransmit 的算法,不以时间驱动,而以数据驱动重传。也就是说,如果,包没有连续到达,就ack最后那个可能被丢了的包,如果发送方连续收到3次相同的ack,就重传。Fast Retransmit的好处是不用等timeout了再重传。
比如:如果发送方发出了1,2,3,4,5份数据,第一份先到送了,于是就ack回2,结果2因为某些原因没收到,3到达了,于是还是ack回2,后面的4和5都到了,但是还是ack回2,因为2还是没有收到,于是发送端收到了三个ack=2的确认,知道了2还没有到,于是就马上重转2。然后,接收端收到了2,此时因为3,4,5都收到了,于是ack回6
ast Retransmit只解决了一个问题,就是timeout的问题,它依然面临一个艰难的选择,就是,是重传之前的一个还是重传所有的问题
SACK 方法
另外一种更好的方式叫:Selective Acknowledgment (SACK)(参看RFC 2018),这种方式需要在TCP头里加一个SACK的东西,ACK还是Fast Retransmit的ACK
在发送端就可以根据回传的SACK来知道哪些数据到了,哪些没有到。于是就优化了Fast Retransmit的算法。当然,这个协议需要两边都支持。
还需要注意一个问题——接收方Reneging,所谓Reneging的意思就是接收方有权把已经报给发送端SACK里的数据给丢了。这样干是不被鼓励的,因为这个事会把问题复杂化了,但是,接收方这么做可能会有些极端情况,比如要把内存给别的更重要的东西。所以,发送方也不能完全依赖SACK,还是要依赖ACK,并维护Time-Out,如果后续的ACK没有增长,那么还是要把SACK的东西重传,另外,接收端这边永远不能把SACK的包标记为Ack。
SACK会消费发送方的资源,试想,如果一个攻击者给数据发送方发一堆SACK的选项,这会导致发送方开始要重传甚至遍历已经发出的数据,这会消耗很多发送端的资源
Duplicate SACK – 重复收到数据的问题
Duplicate SACK又称D-SACK,其主要使用了SACK来告诉发送方有哪些数据被重复接收了。RFC-2883里有详细描述和示例。下面举几个例子(来源于RFC-2883)
D-SACK使用了SACK的第一个段来做标志,
- 如果SACK的第一个段的范围被ACK所覆盖,那么就是D-SACK
- 如果SACK的第一个段的范围被SACK的第二个段覆盖,那么就是D-SAC
引入了D-SACK,有这么几个好处:
1)可以让发送方知道,是发出去的包丢了,还是回来的ACK包丢了。
2)是不是自己的timeout太小了,导致重传。
3)网络上出现了先发的包后到的情况(又称reordering)
4)网络上是不是把我的数据包给复制了。
快速确认&延时确认
如果只是为了确认一个段就发送ack,这样会增加不必要额网络流量,为了解决这个问题最好方法就是延时确认,因为ack不占用tcp段资源,所以可以将ack于数据一起发送给对端。
tcp有两种模式来处理确认接收到的数据,即快速确认以及延时确认,在整个tcp 发送接收过程中,由于网络拥塞 收到小包等原因,会在快速确认以及延时确认之间切换。
当tcp进入延时确认,通常是接收到两个tcp 段产生一个确认或者延时在0.5s之类产生一个确认。
当前代码中存在检查是否在快速确认模式函数,但是太复杂了,
在延迟确认模式中,本端接收到数据包后,不会立即发送ACK给对端,而是等待一段时间,如果在此期间:
1. 本端有数据包要发送给对端。就在发送数据包的时候捎带上此ACK,如此一来就节省了一个报文。
2. 本端没有数据包要发送给对端。延迟确认定时器会超时,然后发送纯ACK给对端。
在具体实现中,用pingpong来区分这两种模式:
icsk->icsk_ack.pingpong == 0,表示使用快速确认。
icsk->icsk_ack.pingpong == 1,表示使用延迟确认。
快速确认模式是用于比较紧急的场景,此时需要立即通知对端,比如收到异常的数据报、接收窗口显著增大了。延迟确认模式则希望通过减少纯ACK的发送,来降低不必要的流量开销,所以此时要求数据的传输是双向的。在实际的传输过程中,会根据当时的场景来判断是使用快速确认模式还是延迟确认模式,因此ACK的发送模式并不是固定的,而是在这两种模式之间动态切换。
什么时候进行快速确认?
目前以下一种情况会导致快速确认
1、fin_wait1 以及fin_wait2状态下接收到fin
2、syn_sent状态下,paws校验失败或已接收到确认段,发送dack。
3、在接收慢路径下,paws校验失败或者已接收到确认段,发送dack
4、接收到多个全尺村的段且接收窗口的右端已经更新,也就是接收缓冲区中有一个以上的全尺寸数据段仍然是NOT ACKed,并且接收窗口变大了
5、设置TCP_QUICKACK选项之后:进入快速确认模式,并立即发送一个ACK,这个选项并不是持久的,之后还是有可能进入延迟确认模式的
6、乱序tcp段队列中还有待处理的段
7、连续接收到两个小包,小于536B
8、接收到数据包的事件处理 (tcp_event_data_recv):数据包含有路由器的显式拥塞通知,进入快速确认模式
9、如果接收到的段有负荷,且其中一部分之前已经接收过了,则认为是Delayed ACK丢失,进入快速确认模式
转自参考:https://blog.csdn.net/zhangskd/article/details/45127565
Q:什么时候进行快速确认?
(1) 接收到数据包,检查是否需要发送ACK时 (__tcp_ack_snd_check):
1. 接收缓冲区中有一个以上的全尺寸数据段仍然是NOT ACKed,并且接收窗口变大了。
所以一般收到了两个数据包后,会发送ACK,而不是对每个数据包都进行确认。
2. 接收到数据包时,处于快速确认模式中。
3. 接收到数据包时,乱序队列不为空。
(2) 当接收队列中有数据复制到用户空间时,会判断是否要立即发送ACK (tcp_clean_rbuf):
如果现在有ACK需要发送,满足以下条件之一,就可以立即发送:
1. icsk->icsk_ack.blocked为1,之前有Delayed ACK被用户进程阻塞了。
2. 接收缓冲区中有一个以上的全尺寸数据段仍然是NOT ACKed (所以经常是收到2个全尺寸段后发送ACK)
3. 本次复制到用户空间的数据量大于0,且满足以下条件之一:
3.1 设置了ICSK_ACK_PUSHED2标志
3.2 设置了ICSK_ACK_PUSHED标志,且处于快速确认模式中
如果原来没有ACK需要发送,但是现在的接收窗口显著增大了,也需要立即发送ACK通知对端。这里的显著增大是指:新的接收窗口大小不为0,且比原来接收窗口的剩余量增大了一倍。
什么时候进行延迟确认?
1. 快速确认模式中的ACK额度用完了,一般在快速确认了半个接收窗口的数据后,进入延迟确认模式。
2. 发送ACK时,因为内存分配失败,启动延迟确认定时器。
3. 接收到数据包,检查是否需要发送ACK时(__tcp_ack_snd_check),如果无法进行快速确认。
4. 使用TCP_QUICKACK选项禁用快速确认,设置的值为0。
https://coolshell.cn/articles/11609.html
https://blog.csdn.net/zhangskd/article/details/45127565
tcpack---1简述的更多相关文章
- 简述 OAuth 2.0 的运作流程
本文将以用户使用 github 登录网站留言为例,简述 OAuth 2.0 的运作流程. 假如我有一个网站,你是我网站上的访客,看了文章想留言表示「朕已阅」,留言时发现有这个网站的帐号才能够留言,此时 ...
- JavaScript单线程和浏览器事件循环简述
JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...
- Design Patterns Simplified - Part 3 (Simple Factory)【设计模式简述--第三部分(简单工厂)】
原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part3-factory/ Design ...
- Android网络定位服务定制简述
Android 添加高德或百度网络定位服务 Android的网络定位服务以第三方的APK方式提供服务,由于在国内Android原生自带的com.google.android.gms服务几乎处于不可用状 ...
- 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述
微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...
- 简述ASP.NET MVC原理
1.为什么ASP.NET需要MVC? 因为随着网站的的数量级越来越大,原始的网站方式,这里指的是WebForm,在运行速度和维护性方面,以及代码量上面,越来越难以满足日益庞大的网站维护成本.代码的重构 ...
- Design Patterns Simplified - Part 2 (Singleton)【设计模式简述--第二部分(单例模式)】
原文链接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/ De ...
- 【翻译】设计模式学习系列1---【Design Patterns Simplified: Part 1【设计模式简述:第一部分】】
原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part1/ Design Pattern ...
- Android开发3:Intent、Bundle的使用和ListView的应用 、RelativeLayout(相对布局)简述(简单通讯录的实现)
前言 啦啦啦~博主又来骚扰大家啦~大家是不是感觉上次的Android开发博文有点长呢~主要是因为博主也是小白,在做实验的过程中查询了很多很多概念,努力去理解每一个知识点,才完成了最终的实验.还有就是随 ...
- iOS开发路线简述
1 iOS开发环境1.1 开发环境标准的配置是MacOSX+Xcode.MacOSX的话首选用苹果电脑,Macmini最便宜只要4000多就好了然后自己配一个显示器,MacBookPro 也可以,不推 ...
随机推荐
- 实验六 DIV+CSS的综合应用
实验六 DIV+CSS的综合应用 [实验目的] 1.掌握DIV布局的方法: 2.利用CSS对DIV进行美化: 3.利用CSS对文本图像等网页元素进行美化 [实验环境] 连接互联网的PC ,Win7操作 ...
- Rust之路(2)——数据类型 上篇
[未经书面同意,严禁转载] -- 2020-10-13 -- Rust是系统编程语言.什么意思呢?其主要领域是编写贴近操作系统的软件,文件操作.办公工具.网络系统,日常用的各种客户端.浏览器.记事本. ...
- Spring Boot 系列:最新版优雅停机详解
爱生活,爱编码,本文已收录架构技术专栏关注这个喜欢分享的地方. 开源项目: 分布式监控(Gitee GVP最有价值开源项目 ):https://gitee.com/sanjiankethree/cub ...
- day46 Pyhton 数据库Mysql 03
一内容回顾 存储引擎:主要描述的是数据存储的不同方式 innodb 支持事务\支持外键\行级锁\聚焦索引 myisam 不支持事务\不支持外键\表级锁\非聚焦索引 memory 只能在内存中存储表数据 ...
- jenkins 构建 job 并获取其状态的实现
目录 BACKGROUND INVESTIGATION I 1. 连续触发的相同 job 构建不会重复入队 2. 连续触发的不同 job 构建会各自入队 3. 参数变动的相同 job 构建将分别入队 ...
- pytest文档54-Hooks函数terminal打印测试结果(pytest_report_teststatus)
前言 使用命令行执行pytest用例的时候,会在 terminal 终端打印整个用例的测试结果: .代表通过的用例 F代表失败的用例 E代表异常的用例 如果我们不喜欢这种报告结果,可以通过 pytes ...
- 【博弈论】51Nod 1534 棋子游戏
题目内容 波雷卡普和瓦西里喜欢简单的逻辑游戏.今天他们玩了一个游戏,这个游戏在一个很大的棋盘上进行,他们每个人有一个棋子.他们轮流移动自己的棋子,波雷卡普先开始.每一步移动中,波雷卡普可以将他的棋子从 ...
- golang拾遗:为什么我们需要泛型
从golang诞生起是否应该添加泛型支持就是一个热度未曾消减的议题.泛型的支持者们认为没有泛型的语言是不完整的,而泛型的反对者们则认为接口足以取代泛型,增加泛型只会徒增语言的复杂度.双方各执己见,争执 ...
- Linux用户和组管理命令-用户属性修改usermod
用户属性修改 usermod 命令可以修改用户属性 格式: usermod [OPTION] login 常见选项: -u UID: 新UID -g GID: 新主组 -G GROUP1[,GROUP ...
- 微信小程序的账号找回。
之前注册过微信小程序,好久没用了,马上要开发微信小程序了,我今天登陆了一下突然发现 然后点击账号找回,按照流程同意点击下一步,到第二部时要输入搜索框里的提示. 这时的我早已忘了,百度搜了一下如何找回原 ...