| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 网络协议 -> TCP可靠传输机制 -> 正文阅读 |
|
[网络协议]TCP可靠传输机制 |
目录 顺着上一篇TCP/IP 报文&协议学习_ykdsg的博客-CSDN博客?继续研究了下TCP?的相关机制,虽然也不深入。 关于TCP 的异常状态CLOSE_WAIT:这是一个在服务端的确认关闭连接的状态。在某些情况下我们会看到服务端有大量的 CLOSE_WAIT 存在,而导致了这一情况发生,大概率是因为客户端发起请求关闭连接后就立刻退出了把服务端晾在那了(即不往下走关闭流程)。在liunx系统中会默认等待7200秒才开始进行连接探测,默认探测大约11分钟(间隔75秒的9个探头)后,空闲连接才会被终止;可以通过某些系统参数进行优化。
TIME_WAIT:这是一个在客户端最后等待关闭 2MSL 值后进行连接关闭及清理工作。在高并发场景下主动发起FIN报文段断开连接,那么此时就会出现大量的TIME_WAIT。可以通过系统参数优化。
可靠传输:RDT(可靠数据传输协议):定义了如何构造出一个可靠传输信道:
协议特性:
?
TCP 确认机制发送方发送segment 1,接收方收到之后需要ACK确认,这个时候ACK = 2 ,意思是说,segment 1已经成功接收,寡人等待segment 2的到来。如果发送方发送的segment是“1、2、3、4、5、6”,接收方应该收到“2、3、4、5、6、7”,当接收方接到ACK =7,就意味着编号7前面所有segment都成功接收,在这里就是“1、2、3、4、5、6”都成功接收了。 问题是ACK的次数有点多,接收方发送一次ACK耗费CPU,接收方接到一次ACK也耗费CPU,另外ACK报文对网络也是一个小小的负担。于是RFC建议优化ACK方法,每收到2个segment,发送一次ACK,这样就会将ACK数目减半。那么接收方可以这样ACK :“3、5、7。。。”,当发送方接收到ACK=7,表明segment 1、2、3、4、5、6已经到了。 问题来了,如果发送方只有一个segment发送,按照以上规则,接收方接收2个segment才发送一个ACK,既然只有一个segment,那接收方的ACK会不会永远也发不出?这里会造成通信的死锁(deadlock)。TCP会启动一个定时器,只要闹钟响了(timeout)而第二个segment还没有到,这时就顾不了那么多,直接发ACK就好。TCP 慢启动(slow start)就是先发segment 1,直到接到对方ACK了,才会发segment 2、3。有了这个定时器,就可以避免TCP慢启动期间的通信死锁。 假如发送方发送segment “1234567”,接收方接到的是“1235”,接收方接到5的那一瞬间,知道4有可能丢了,也有可能乱序了,至于是哪种情况,接收方无从知晓。 但发送方对于segment 4的状态是完全空白的,既然接收方知道多一点,就把这个信息同步给发送方。 通过什么方法把消息同步给发送方呢? ACK =4 有同学会迷惑不解,明明收到的是5,应该ACK= 6,为何这里是4? ACK=6 是什么意思? 表示 “12345”都成功接收,问题是4收到了吗? 没有啊!所以只能ACK=4。 稍后,接收方所有接收到的segment为 “12356”,接收方如何做? ACK=4 再稍后,接收方所有接收到的segment为 “123567”,接收方如何做? ACK =4 发送方一直记录自己重复收到某个ACK的次数,Duplicated ACK(4) =3,此时发送方意识到segment 4有可能丢了,此时应该立马主动将segment 4重传出去,而不要被动等待segment 4的重传定时器超时再重传segment 4。 由于这种依赖外界刺激的重传方法比超时重传更快、更及时,美其名曰:快速重传(Fast Re-transmit)。 当重传的segment 4到达接收方时,终于将不连续的segment流 “123567” 修复(Restore)成连续的segment流 “1234567”,通常称这种主动修复字节流的方法为快速修复(Fast Restore)。两者合在一起统称Fast Re-transmit / Fast Restore。 上文说的外界刺激,就是发送方连续收到三次duplicated ACK,立马启动Fast Re-transmit / Fast Restore机制。 如果上文中的接收方所有接收到的segment 不是“123567”,而是”123564”,此时就是乱序的发生,接收方会重新排序成”123456” ,接收方发送ACK =7即可,segment是连续的,无需修复。 在这种情况下,发送方只接到了两次duplicated ACK =4,无需启动Fast Retransmit / Fast Restore机制,因为接收方已经成功修复。 TCP可靠传输
TCP的滑动窗口的作用:一种是提供可靠性(通过重传方式确保所有分组的ack),还有另一种是提供流控特性(窗口的大小来控制) 流量控制在TCP中滑口的大小是取决于rwnd(接收窗口)和另一个cwnd(拥塞窗口),当哪个值小哪个值就是滑动窗口,即TCP中window的大小。 ?rwnd:TCP 为了消除发送方使接收方缓存溢出的可能性,因此需要对双方流量做一个控制达到一个速度匹配的状态,即发送方的发送速率与接收方应用程序的读取速率相匹配。所以TCP在连接两端的发送方各自维护一个rwnd,rwnd的值是由接收方在发送ACK时放入window字段发送给发送方,而且这个值是动态的它的大小是取决于接收方读取缓存数据的速度。 cwnd:在发送方都维护的这么一个窗口变量,其值取决于网络的拥塞程度而且是动态变化,它会对发送方进行一个发送的流程限速。 拥塞控制拥塞控制就是为了尽量让网络设备接近它最高核载进行工作(压榨它的极限),但又不至于它出现过载的情况。 TCP的拥塞控制四种算法:慢启动、拥塞避免、快速重传、快速恢复 慢启动假设当前发送方拥塞窗口(cwnd)的值为 1个 MSS值,当传输了第一个报文段并且接收到ACK后,cwnd就会增加 1个 MSS (现在window size 是 2MSS)。那么下一次就会同时发送2个报文段,等待接收到2个报文段后就会再增加2个 MSS。这么循环往复直到cwnd的值变为16,16这个值我们称为ssthresh(慢启动阀值),其实它也是一个动态值等下一阶段拥塞避免时会动态调整。 拥塞避免经过一番慢启动之后我们便进入拥塞避免,此时的cwnd变成变成了线性加 1,如同时发出16个报文段并收到16个报文段后cwnd才会+1,也就是cwnd变为 17 MSS。 现在假设cwnd是24MSS,在下次报文传输中发送方收到了3个冗余ACK,在此之前我们说过TCP如果收到3个冗余ACK就会进行快速重传。并且ssthresh值就会调整为12MSS (cwnd/2)即cwnd的一半,最后cwnd设置为 1 MSS 并进入快速恢复或慢启动 阶段。 快速重传:当发送方等待到3个冗余 ACK 的时候就会立刻重传而无需等待分组超时。那为什么是3个冗余ACK?因为 ACK 的发送是由接收方决定什么时候发的这个ACK,所以在延迟网络中会产生一连串的冗余ACK, 这些ACK的产生和前面提到FSM机制有联系,在某个状态下通过不同的事件来决定。(如:序号大的分组先到达了,但期望的分组还没到,这时接收方就会立刻发送一个期望分组的ACK)。 快速恢复:快速恢复在TCP里面是一个推荐组件,但其实已经纳入在新版的TCP里面而且不断的迭代更新。我们现在来看看最早期的拥塞控制(Tahoe 和 Reno)算法,快速恢复这个机制在Reno算法中才出现的,后面的算法也会沿用这个概念。 这两种算法在对于丢包事件判断都是以RTO(retransmission timeout,超时重传)和冗余ACK为条件,但两者的做法是不同的;
网上找的示意图: TCP的公平退让原则其实就是受到拥塞控制的影响,因为只要出现丢包就会大幅度降低速率。因为拥塞窗口总体看来其实“加性增,乘性减”,所以在多个TCP端在传输的时候就会通过丢包的方式往复的触发拥塞控制,最终达到让速率稳定在一个不丢包的状态。 |
|
网络协议 最新文章 |
使用Easyswoole 搭建简单的Websoket服务 |
常见的数据通信方式有哪些? |
Openssl 1024bit RSA算法---公私钥获取和处 |
HTTPS协议的密钥交换流程 |
《小白WEB安全入门》03. 漏洞篇 |
HttpRunner4.x 安装与使用 |
2021-07-04 |
手写RPC学习笔记 |
K8S高可用版本部署 |
mySQL计算IP地址范围 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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年11日历 | -2024/11/25 20:50:46- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |