IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: 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的进化之路

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

传输层协议之TCP的进化

丢包和乱序

在下三层中已经能够将数据成功送达目的主机了,那么后面几层的作用就是将数据包准确送到目标进程了。

主机上工作的进程这么多,我们就要对其进行区分,于是使用一个叫做端口号的编号,比如我们常用的http进程绑定的80端口。此时我们又需要给数据包加上一个头,它至少要包含源端口号和目的端口号,此时,倘若再加上包长度和校验值的话,一个叫UDP协议的东西就诞生了呀!

此时,使用UDP协议已经能达到进程之间通信的目的啦!然而,网络往往比咱们想的要复杂,在一个不可靠的网络上传输数据包,很可能到不了目的主机,更别说到目的进程了。

那我们就需要增加一些手段来解决数据包丢失的问题,首先我们要让发送方知道数据包丢失,然后再重传数据包。

最开始的方法是这样的,主机A每发送一个包,都要等待主机B的ACK确认包,如果在一定时间内没有收到确认,则重传,这就是停止等待协议。

显然,这种方法效率太低了,于是我们采取一种流水线式的方法,发送多个包就回复多个ACK确认,此时又会带来新的问题,当发送数据包由于网络延时到达目的主机时出现了乱序问题,于是我们又在主机A发送的数据包中增加一个seq序号,主机B响应的ACK包上增加一个ack确认号(该确认号为收到的最后一个数据包的序号seq+1,表示seq之前的包都收到了,即累计确认)。

流量控制

前面的方法已经可以解决丢包和乱序问题,此时我们就可以随心所欲的发送数据包了吗?答案是可以发,但未必随心所欲。

试想一下,如果主机A发送速度巨快无比,而主机B收包的速度又无比的慢。没错,试想一下节假日堵在高速的我们。

遇到这种问题时,应该让主机A知道主机B自己的接收能力,主机A再控制下发送速度就OK,这个接收能力的大小怎么表示呢,我们用到了一个窗口—滑动窗口(看到这里,大伙是不是开始兴奋啦!)。

于是乎,A和B每次通信都会加上一个表示窗口大小的值,代表自己的接收能力,那么问题来了,对方主机怎么根据这个窗口来控制自己的发送速度呢?

举个例子,当主机B传给主机A的窗口大小为4,即主机B目前还能接收4个数据包,如图:
在这里插入图片描述
如图,绿色区域就是根据主机B目前的窗口大小所控制的数据包个数,主机A将从数据包6开始一直发包直到数据包9发送完毕,在此期间主机B也会发送确认包给A,当主机A收到数据包6的确认时,窗口的右边界将向右移动,主机A将继续向B发送新的数据包。

当然,若主机B发送了一个新的窗口值8,则主机A可发送数据包窗口的大小将变为8;反之,如果收到的窗口值变小,则主机A暂时不会改变窗口大小,也不会将窗口右边界往左回移,而是等着B发送的确认包,将窗口左边界向右移动,直到窗口大小变为新的窗口值为止。

拥塞控制

流量控制是应对对端主机接收能力的变化的策略,而拥塞控制则是应对网络环境变化的策略。

拥塞控制也是通过设置类似窗口大小的方法来应对的,不同于流量控制中主机B的主动通知窗口大小,拥塞控制则是主机A一次次的去探测网络环境好坏,从而确定拥塞窗口(cwnd)的大小。结合上一节流量控制中的接收端窗口大小(awnd),则发送端实际可以用的窗口(W)为两者中的较小值:

W = min(cwnd, awnd)

那么拥塞检测的方法有哪些呢?接下来我们将讨论一些经典的拥塞控制算法。

慢启动
当一个新的连接建立时,需要执行慢启动算法,简单来说,发送方先发送一个单位的数据包,在收到ACK响应之后,窗口cwnd大小变为2,以此类推,在没有丢包且每个数据包都有对应的ACK时,在k轮之后cwnd的值变为2k。

显然发送端实际可用的窗口不可能一直呈指数上升,当窗口达到某个值时,大量的数据包导致网络堵塞甚至瘫痪,这时cwnd的值将减小至原值的一半,而后将转到下一个阶段—拥塞避免。
该图来自《TCP/IP详解卷一  P733》

拥塞避免
在慢启动阶段,拥塞窗口cwnd快速增长至阈值(ssthresh),后续将改变策略,采用一种随时间线性增长的方式,这里具体的公式就不再给出了哈,咱直接上《TCP/IP详解卷1》中的图!
在这里插入图片描述

快重传和快恢复
前面两种算法都是在没有发生丢包的情况下,倘若发生丢包或延时,显然重新由慢启动的最初状态开始是不太合理的。

先上结论,当发送端接收到三个重复的ACK值时,发送端就会判断数据包丢失,此时进行快重传,快重传会将阈值ssthresh更新为原值的一半(具体的我就不写出来了哈),之后再重新进入拥塞避免阶段。

快恢复则是对其进一步补充,再接收到一个重复ACK值时,cwnd值将增加1个单位,而当接收到新的ACK值时,说明前面丢失的数据全部接收完毕,可以恢复到最开始的ssthresh值了。

三次握手和四次挥手

关于握手和挥手的有关细节,在我主页的其他文章也给出了分析哈,链接在这:TCP三次握手、四次挥手以及TIME_WAIT详解

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-02-14 21:34:12  更:2022-02-14 21:35:42 
 
开发: 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/26 9:26:39-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码