计算机网络——如何保证 TCP 传输的可靠性

TCP 是传输层上的协议,它是可靠的,面向连接的。

概括

1. 设置传输格式,包括分为 TCP 段、使用校验和、使用序列号

2. 数据丢失之后的重传,超时重传、快速重传、SACK 选择确认、D-SACK 重复选择确认

3. 流量控制,控制数据包的传输速度,避免接受方处理不及时导致数据丢失,使用的是滑动窗口的方法

4. 拥塞控制,控制传输速度,避免传输数据包过多导致网路拥塞,主要算法:慢启动、拥塞避免、拥塞发生、快速恢复

传输内容形式

图片来源:小林coding

1. 基于数据块传输

TCP 传输数据时,不是直接一整个数据直接发送给接收端,而是分成很多数据段,叫做TCP 段或者报文段去发送,比如一个文件很大时,如果直接发送整个文件,传输的过程就不好控制。

2. 对每个数据段分配一个序列号

TCP 将数据分段之后,为了避免其中一个数据段在传输过程中丢失,就给每个数据段分配系列号,通过验证数据段的序列号来判断是否发生了丢失,或者这个数据段是否重复发送了

3. 校验和

TCP 保证首部和数据的校验和,目的是检验数据在传输工程中的变化,如果收到的数据段的校验和有差错,就表示数据发生了变化,就会丢弃这段。

在传输过程中,难免会因为各种原因,导致数据包发生丢失,丢失后的数据包就会通过重传机制来重新发送确保数据的完整性。

重传机制

TCP 实现可靠传输的方式之一,是通过序列号和确认应答机制。

TCP 中,发送端的数据到达接收端之后,接收端和发送一个 ACK 应答信息,表示已经收到了数据包。但是如果发生了数据丢失,比如发送端的数据丢失了,接收端根本没接收到,或者接收端接收到了,应答信息在中间丢了,都会触发重传机制来确保数据发送接收成功。

常见的重传机制:超时重传、快速重传、SACK(选择重传)、D-SACK (重复选择重传)

超时重传

顾名思义,超时重传就是通过设定一个超时时间,当发送数据之后,这个时间内没有接收到应答信息,发送端就认为数据丢失了,就会重新发送丢失的数据包。

但是问题在于,如何去设置超时时间,超时时间设置长了可能包都丢了有一会儿了才发现丢包了,就像你走马路上每隔一段时间摸下手机在不在口袋里,结果手机都丢了很久了你才摸包发现手机丢了。如果设置过短,就会出现数据还没丢,发送端就判断数据丢失了触发了重传,这样就浪费了资源。

首先确认两个概念:

RTT:往返时间,也就是数据包从发送出去一直到接收到 ACK 应答信息的时间。

RTO:重传超时,也就是超时时间。

在实际中只需要 RTO 超时时间略大于 RTT 往返时间即可,如果在往返时间之后还没有接收到应答,就到了 RTO 超时时间,就触发了超时重传。具体计算方法和公式这里就不贴了。

还有需要注意的就是,如果超时重发的数据,再次超时了,TCP 会将超时时间设为两倍。

快速重传

快速重传,不等待指定的时间,而是根据接收到发送的 ACK 应答信息来判断重传时机。

  • 发送 Seq 1,接收到了回复 ACK2,理解为我收到了 Seq1,现在需要 Seq2;
  • 发送 Seq2,发生了丢失,后续又发送了 Seq3,回复 ACK2;
  • 后续继续发送 4 和 5,因为 2 一直没有收到,于是都回复 ACK2;
  • 此时发送端接收到了三次相同的 ACK ,直到了 Seq 2丢失了,于是在过期时间之前就重传该数据包

解决了超时时间的问题,仍然有一个问题。当 Seq 2  和 3 都发生了丢失,因为一直没接收到 Seq2,所以回复的都是 ACK2。那么此时应该发送端怎么判断哪个包发生了丢失。

如果只重传 Seq2,接收端在这之前接收了 4,5,6,后来在接收到2 后,期待3,发现没有接收到,所以又要进行三次相同的回复,效率低。

如果将从 Seq2之后的三个数据包都重发,很明显出现了重复的数据报,浪费了资源。

SACK 选择确认

选择确认是在返回的 ACK 报文中加上 SACK ,作用是让接收端接收到数据包之后返回一个明确收到某一个数据包的应答报文。

举个例子,比如现在发送端发送一个 Seq 100 的数据包,接收端接收之后返回一个 ACK 100 的应答报文,当该数据包丢失之后,后续比如发送一个 Seq 200 的丢失了,再发送 Seq 300 的数据包,此时接收端返回的应答报文应该是 ACK 200,和 SACK 300,再发送一个 Seq 400 时,返回 ACK 200+SACK 400,三次过后,接收端没有收到 SACK 200 的选择应答,所以接收端重发 Seq 200。

D-SACK 重复选择确认

发送方重传的本质原因是没有接收到接收方的应答报文 ACK,而没有收到应答报文又有两种情况:

1. 数据包丢失或者网络阻塞

2. 数据包到达了接收方,而 ACK 应答报文丢失

出现重复数据包一半是网络阻塞和ACK 应答丢失造成的。当 ACK 应答报文丢失之后,实际数据包,比如 Seq 200 是发送到了接收端的,可是发送端认为没有发送到,所以会触发快速重传,重传之后的数据包到达接收端之后,再次返回 ACK 600 + SACK 200的,以为已经到了 ACK 600,表示600前面的数据包已经送达,而 SACK 200就表示这个 Seq 200 是重复的。

这就是重复选择确认。

流量控制

当发送方发送数据包存在一定速率,当速率过快,接收方不能及时处理这些数据,就可能导致数据包丢失。想要控制数据包的发送速率,使用了滑动窗口 的概念用来控制速率。

在之前说到的发送数据包都是收一个回复一个,很明显效率很低,引入滑动窗口,会在操作系统开辟一个缓冲区,当数据包到达接收方放入缓冲区,等待当前正在处理的数据包处理完成再从缓冲区取。这样就可以实现发送方连续发送多个数据包而不用等待每一个数据包的应答报文。

打个比方,有一家面馆,原来只有一个座位供顾客坐着吃面,其他人只能打包回去吃,这样就会少很多想要坐着吃的顾客,后来面馆赚钱了,把店面扩大了,座位增加到了10个,只要顾客吃面的速率和来顾客的速率差不多,就不会有顾客因为看见店里满了而选择另一家店了。顾客就相当于数据包,当接收方不能及时处理数据包时,就让数据包去缓冲区等着被处理。如果发送方速率过快,就会导致缓冲区满了而丢失数据包。

需要注意的是,滑动窗口大小会被操作系统控制,不是一直不变的。

拥塞控制

数据包是通过网络发送到接收方的,网络资源并不是无限的,所以如果发送方发送的太频繁,不仅是接收方处理不过来,首先网络可就先阻塞了。

所以需要一个拥塞窗口来控制发送方发送数据包的速率。拥塞窗口会根据网络情况进行变化,网络没有拥塞就会扩大,如果出现拥塞就会缩小。

控制拥塞的主要算法:

慢启动、拥塞避免、拥塞发生、快速恢复

慢启动

TCP 连接之后拥塞窗口不是一下就设置很大的,就像健身,你要从最轻的哑铃练起,要是你直接抱起100kg的东西,那还不闪了摇。。。

每当发送方接受到一个应答报文 ACK,拥塞窗口就会+1,表示现在网络没有拥塞,报文还能传过来。比如一开始是1,接收到一个 ACK 就是2,下一轮回来两个 ACK ,窗口就会被设置为4,同理,再下一轮就是 8,呈指数形式增长。

但是窗口也不能无限增长,否则和没有窗口限制没区别,用来控制最大窗口的叫做 慢启动门限

当拥塞窗口小于慢启动门限时,就会增加,如果大于等于了,就会触发拥塞避免算法。

拥塞避免

拥塞避免,就是避免拥塞窗口开的太大,当拥塞窗口大于等于慢启动门限时,窗口扩大的速度就会变慢,每次增长 1/当前拥塞窗口大小。比如此时是 8 ,触发拥塞避免算法,于是接收到一个 ACK 扩大 1/8,一轮就是只增加 1 。增长速度就变成了线性增长。

网络不拥塞的情况下,窗口一直增长,直到网络出现了拥塞,数据包被堵在了网络上,一段时间之后,就触发的超时重传机制。于是发送方知道此时网络出现了拥塞,于是触发了拥塞发生算法。

拥塞发生

拥塞发生,发送端触发了超时重传,于是启动了拥塞发生算法,这个算法会重置慢启动门限和拥塞窗口。

慢启动门限会被设置为当前拥塞窗口的一半,拥塞窗口会被重置为初始状态。

看得出来这种方法会导致一切重来,传输速度变慢,5G网变回3G。

于是就有触发快速重传机制之后的 快速恢复 算法。

将拥塞窗口设置为当前的一半,然后将慢启动门限设为拥塞窗口的大小。

就相当于拥塞窗口再以线性增长的速度进行扩大。

快速恢复

快读恢复是在触发了快速重传之后使用的算法,快速重传是发送方接收到了3个相同的 ACK 应答报文才触发的,既然能接收到3个相同的 ACK 应答报文,就是说当前的网络也不是那么糟糕,只需要降低一点就可以。

于是就把拥塞窗口设置为当前的一半,慢启动门限设置为拥塞窗口的大小。具体过程:

1. 首先将拥塞窗口设置为当前的一半 + 3,因为是收到了3个重复的 ACK 应答报文

2. 造成拥塞的主要原因是数据包,而这些数据包都还没有送到接收方,所以要尽量把这些数据包发到接收方,所以如果后续收到的还是重复的 ACK,就把拥塞窗口+1,表示收到的是丢失的数据包。

3. 如果收到收到的新的 ACK ,则表示在此之前的数据包都已经收到了,然后就把拥塞窗口设置为当前的一半。

快速恢复不像拥塞发生,保证速率的同时能解决网络拥塞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/20136.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

字符串-至多包含K种字符的子串中最长子串(mid)

一、题目描述 二、解题思路 借鉴以下题目思想,使用双指针,外层循环右侧指针移动,内存循环左侧指针移动 字符串-最长不含重复字符的子字符串(mid)-CSDN博客文章浏览阅读622次,点赞17次,收藏4次。java刷题:…

探索第三方美颜SDK:美颜插件的技术原理

本篇文章,我们将深入了解第三方美颜SDK,主要探讨关于美颜插件的工作机制与算法。 一、第三方美颜SDK的概述 第三方美颜SDK是由专业团队开发的一套用于实现美颜功能的软件开发工具包。它通常包括了各种美颜算法、滤镜效果、人脸识别等核心技术&#xff…

Kafka broker的新增和剔除(服役与退役)

说明:集群现有broker:node1,node2,node3三个,broker.id分别为0,1,2 已有两个topic:products、cities 1、退役(Kafka集群中减少一个服务器broker2) 退役后要保证剩下的服务器数量大于等于备份数&#xff0c…

软件设计不是CRUD(21):在流式数据处理系统中进行业务抽象落地——需求分析

本文主要介绍如何在数据处理系统中应用业务抽象的设计思想。目前业界流行的数据处理方式是流式处理,主流的流式处理引擎有Apache Spark,Apache Flink等等。本文选择Apache Flink作为实战案例的落地。由于本文主要是讲解设计思想和流式处理引擎相结合的方…

排八字软件有哪些?

排八字软件有哪些?在市面上有很多排八字的软件可供选择,其中一些比较知名的有: 无敌八字排盘软件:这是一款功能强大的八字排盘软件,提供详细的八字解析和命理分析服务,且完全免费。 网易星盘:网…

【一百】【算法分析与设计】N皇后问题常规解法+位运算解法

N皇后问题 链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述 给出一个nnn\times nnn的国际象棋棋盘,你需要在棋盘中摆放nnn个皇后,使得任意两个皇后之间不能互相攻击。具体来说,不能存在两个皇后位于同…

自用了很久的一款强制卸载软件,超级好用!!!

Ashampoo UnInstaller是一款由Ashampoo公司开发的专业卸载工具,它提供了比Windows自带卸载功能更为彻底的程序卸载解决方案。是一款功能强大的卸载工具,旨在帮助用户彻底删除不需要的程序和应用,卸载难以卸载的软件工具,此外他还有…

面试杂谈k8s

其实看我之前的博客,k8s刚有点苗头的时候我就研究过,然后工作的时候间接接触 也自己玩过 但是用的不多就忘记了,正苦于不知道写什么,水一篇 用来面试应该是够了 支持云应用开发、运行与运维一体化的云应用平台软件应运而生 k8s核…

智慧车站管理:提升地铁站新质生产力的策略

应用图扑自研产品 HT for Web 结合 BIM 技术,搭建轻量化的 WebGIS 智慧车站系统。 该系统通过整合轨道交通信息,实现了车站数据的多维互联与融合。提升了车站信息管理效率和运营效能,并优化了乘客出行体验。对构建智能、高效、环保的轨道交通…

使用C#实现VS窗体应用——画图板

✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。🍎个人主页:Meteors.的博客💞当前专栏:小项目✨特色专栏: 知识分享&#x1f96d…

前端树形结构组件的设计与实现:以企查查、天眼查股权结构为例

摘要 随着信息化时代的不断发展,数据可视化在各行各业的应用越来越广泛。特别是在商业信息查询领域,如企查查、天眼查等平台,通过直观的数据展示方式,帮助用户快速理解复杂的商业关系。本文将以一个前端tree树形结构模版组件为例…

【算法】模拟算法——替换所有的问号(easy)

题解:替换所有的问好(模拟算法) 目录 1.题目2.题解3.参考代码4.总结 1.题目 题目链接:LINK 2.题解 纯模拟。从前往后遍历整个字符串,找到问号之后,就⽤ a ~ z 的每⼀个字符去尝试替换即可。 3.参考代码 class Solution { pu…

使用docker部署项目

一、docker私有镜像仓库 1、docker私有镜像仓库 库(Repository)是集中存放镜像的地方,又分为公共镜像和私有仓库。 当我们执行docker pull xxx的时候,它实际上是从registry.docker.com这个地址去查找,这就是Docker公…

城市之旅:使用 LLM 和 Elasticsearch 简化地理空间搜索(二)

我们在之前的文章 “城市之旅:使用 LLM 和 Elasticsearch 简化地理空间搜索(一)”,在今天的练习中,我将使用本地部署来做那里面的 Jupyter notebook。 安装 Elasticsearch 及 Kibana 如果你还没有安装好自己的 Elasti…

EitbaseEX香港业务开展,提升用户友好交易体验

在全球范围内备受瞩目的加密货币交易平台Coinbase,宣布正式入驻香港市场,并命名为EitbaseEX。这一战略性扩展举措,旨在为香港提供先进的加密货币交易技术和服务,同时将香港打造为其在亚太地区的重要枢纽。 作为国际金融中心&#…

Nginx 文件下载 限速设置 限制访问频率 下载速率 并发连接数 简单实用教程

1 没有限速之前 2 nginx配置 #增加如下配置 limit_conn_zone $binary_remote_addr zoneaddr:10m; location / {limit_conn addr 1; #按照来源,限制每个IP 的连接数为1limit_rate_after 1000k;不限速下载的数据量limit_rate 100k; #限制最大传输速率root /data/log…

sudo命令的隐患-要注意安全使用!!严格管理!!严格控制

前言 众所周知,sudo命令非常方便,而且有一定的优点。比如不需要知道root密码就可以执行一些root的命令。相比于su 必须知道root密码来说,减少了root密码泄露的风险。 但是sudo也是一把非常锋利的双刃剑,需要加以限制,…

翻译《The Old New Thing》- What a drag: Dragging a virtual file (IStream edition)

What a drag: Dragging a virtual file (IStream edition) - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080319-00/?p23073 Raymond Chen 2008年03月19日 拖拽虚拟文件(IStream 版本) 上一次,我们看…

python | 类的实现

和实例有关的,通过对象名,打点调用 实例属性,实例方法 stuStudent("XiaoMing",18) print(stu.name) 类属性、静态方法和类方法都是通过类名直接调用 Student.name 静态方法和类方法都不能调用实例属性和实例方法 动态绑定 如果是函…

深入分析 Android Service (四)

文章目录 深入分析 Android Service (四)1. 使用 Messenger 进行通信2. 详细示例:使用 Messenger 进行通信2.1 创建 MessengerService2.2 在 Activity 中绑定服务并发送消息 3. 使用 AIDL 进行进程间通信3.1 定义 AIDL 接口3.2 实现 AIDL 接口3.3 在客户端绑定 AIDL…