TCP如何保证可靠传输,为什么应用层还需要确认机制

news2024/12/22 23:56:31

TCP的可靠传输实现

以下区别:
1、可靠传输(有序,保证对方一定接受到)
2、流量控制
这两个功能都是依靠滑动窗口来实现的
TCP实现可靠传输依靠的有 序列号自动重传滑动窗口确认应答等机制。

序列号

首先我们说下序列号,TCP中将要发送的数据包的每个字节都分配了序列号,用来唯一标识一个字节。序列号随着数据包的发送而增加。
只有为每个字节分配一个序列号,每个数据包都对应着一个序列号区间,才能确定哪个数据包发送出现意外了。
序列号的初始化是由操作系统分配的,是一个32位的数字。
TCP初始化序列号不能设置为一个固定值,因为这样容易被攻击者猜出后续序列号,从而遭到攻击。
RFC1948中提出了一个较好的初始化序列号ISN随机生成算法。

ISN = M + F(localhost, localport, remotehost, remoteport).

M是一个计时器,这个计时器每隔4us加1。
F是一个随机算法,根据源IP、目的IP、源端口、目的端口生成一个随机数值。

确认应答

当接收方收到一个数据包后,会直接返回一个ACK包,或者延迟一段时间返回一个ACK包,一次性确认多个数据包。
ACK包中有一个ack字段,代表着seq小于ack的数据包都已经被接收完毕。
在这里插入图片描述

自动重传 ARQ

当TCP发送端发送了一个TCP数据包的时候,会设置一个定时器,如果在定时器期间没有收到接收方对这个数据包的确认应答包,也成为ACK包,就会重新发送对应的TCP数据包。
自动重传有以下两个原因:
1、数据包丢失
2、ack数据包丢失
在这里插入图片描述

超时时间的选择
超时时间既不能太长,又不能太短。
超时时间过长存在的问题:
当发生丢包的时候,需要等待好长时间才会重新发送,这个时候TCP就处于等待时期,什么也干不了,浪费资源,发送效率低下。
超时时间过短存在的问题:
如果超时时间太短,会发生多次发送重复包的情况。当ACK包还在路上的时候,由于超时时间太短而导致发送端重复的发送不必要的数据包。会加重网络的负担,导致网络阻塞等问题。网络发生阻塞的话,会进一步正反馈导致更多的重传。
重传超时时间简称为RTO
RTO是略大于RTT的。
RTT指的是一个数据包从发送到接收到ACK确认包的花费时间,RTT是会随着网络的变化而变化,是会波动的。

TCP缓冲区

什么是tcp缓冲区?每个 socket 被创建后,都会分配两个缓冲区,输入缓冲区和输出缓冲区。
二、缓冲区的意义
write()/send() 并不立即向网络中传输数据,而是先将数据写入缓冲区中,再由TCP协议将数据从缓冲区发送到目标机器。一旦将数据写入到缓冲区,函数就可以成功返回,不管它们有没有到达目标机器,也不管它们何时被发送到网络,这些都是TCP协议负责的事情。
TCP协议独立于 write()/send() 函数,数据有可能刚被写入缓冲区就发送到网络,也可能在缓冲区中不断积压,多次写入的数据被一次性发送到网络,比如nagle算法,这取决于当时的网络情况、当前线程是否空闲等诸多因素,不由程序员控制。
read()/recv() 函数也是如此,也从输入缓冲区中读取数据,而不是直接从网络中读取。

滑动窗口的出现原因

滑动窗口 分为 发送窗口接收窗口
发送窗口 用来 发送数据
接收窗口 用来 接收数据
客户端和服务器端 都有一个 发送窗口接收窗口
在这里插入图片描述

为什么会引入滑动窗口呢?
如果不存在发送窗口的话,TCP发送一个数据包后会等待ACK包,因为必须要保存对应的数据包,数据包很有可能需要重新发送。
这样的话发送效率会很慢。大部分时间都在等待。
在这里插入图片描述

引入了发送窗口,发送窗口的做法是:
只要处于发送窗口范围中的数据包都可以被发送,不需要等待前面数据包的ack包。
如果发送窗口的大小为3个TCP数据包,那么发送方就可以连续发送3个TCP数据包,而不用等待前2个数据包的ack包。
在这里插入图片描述

滑动窗口详解

发送窗口

在这里插入图片描述

发送窗口存在于操作系统中开辟的一块缓冲区,用来存放当前需要发送的数据。本质是一个循环数组的实现。利用三个指针来维护相关的区域。
发送窗口就是一个循环利用的缓冲区,应用层发送数据,就是往缓冲区中写入数据。收到ACK后,就相当于从缓冲区中移除数据,不过并不会真正移除数据,只需要后移对应的指针就可以了。
应用层会将数据写入到缓冲区中,当超过缓冲区的最大地址后,就循环利用头部,覆盖头部的数据。
发送缓冲区分为四个部分:
1、已经收到ack包的数据
已经收到ack包的数据,代表接收窗口已经接收了对应的数据,可以被新数据覆盖。
2、已经发送还未接收到ack包的数据
已经发送出去,但是还未收到接收方对应的ack包
3、允许发送但是还未发送的数据
允许发送但是还未发送的数据。
4、不允许发送的数据。
发送窗口之外的数据,排队等待后续发送。
区间2 和 区间3 构成了发送窗口,两个区间的大小总和对应着发送窗口的大小
TCP中用三个指针来区分这个四个部分
在这里插入图片描述

指针1: 指向第一个已发送但是未接收到ack的字节
指针2: 指向第一个允许发送但是还未发送的字节
指针3: 发送窗口的大小
这时还允许发送数据,就会将可用窗口中的数据发送给接收窗口。
在这里插入图片描述

这个时候,可用窗口大小为0,这个时候会等待接收方发送ack包。
如果这个时候如果接收一个ack包为37,这个时候发送窗口会向右边移动5位,52-56会变成可用窗口。

在这里插入图片描述

接收窗口

接收窗口中的字节序列号都是与发送窗口一一对应的。
在这里插入图片描述

接收窗口也是存在于操作系统中开辟的一块缓冲区,用于接收数据。缓冲区本质是一个循环数组的实现。利用两个指针来维护相关的区域。
接收窗口存在于一个循环利用的缓冲区,接收数据 就是往缓冲区中写入数据。应用层读取数据后,就相当于从缓冲区中移除数据,不过并不会真正移除数据,只需要后移对应的指针就可以了。
当数据写入超过缓冲区的最大地址后,就循环利用头部,覆盖头部的数据。
缓冲区分为三部分:
1、应用层已经读取的数据
已经接收到的数据,并且已经发送了ack包,并且已经被应用层读取。
2、接收窗口中的数据
接收窗口中存储的是当前允许被接收的数据。
接收窗口允许无序接收数据包,所以接收窗口中有一部分数据接收到了,一部分没接收到,将无序的数据包直接缓存到接收窗口中。接收窗口允许无序接收数据包,所以接收窗口中有一部分数据接收到了,一部分没接收到,将无序的数据包直接缓存到接收窗口中。
因为无序的接收数据包,接收窗口中是存在空隙的,因为先发送的数据包由于网络原因,反而可能会后到接收方。
当数据包缓存到接收窗口中,就会返回ack包,ack包中会携带SACK信息,也就是选择重选信息。
3、还未收到的数据
还不能接收数据的区域,也就是接收窗口之外的数据。
接收窗口由一个RCV_NEXT和接收窗口大小WND来维护。
RCV_NEXT
下一个希望接收的数据包的序列号,当接收到对应的数据包后,会将RCV_NEXT右移,右移到缓冲区中第一个为空的位置。
同时将WND 减去 移动的个数
WND
接收窗口的大小。
WND有以下两种变化:
1、接收窗口 有序的接收到对应的数据包,WND会减去对应的数据包长度。
2、应用程序读取了数据包 必须连续读,不能跳过间隙读取,会将WDN增加对应的数据包的长度
接受缓冲区的wind只有被应用程序读取后才会 变大右移。否则只会不断变小
接收窗口详情
接收窗口接收数据包后,即使应用程序没有读取对应的数据包,也会立马返回ack应答包,ack应答包中会携带当前接收窗口的大小WND和接收窗口的数据包缓存信息。
1、当数据包的seq == RCV_NEXT的数据包的时候,将接收窗口的RCV_NEXT右移到缓冲区中第一个为空的位置,WND减去对应的移动字节数 RCV_NEXT移动会发送对应的ACK数据包;
2、当数据包的seq > RCV_NEXT 并且 seq < RCV_NEXT+ WND的时候,会将其加入到滑动窗口中对应的位置。
3、如果数据包的seq < RCV_NEXT,说明该数据包已经被接收了,但是对应的ack包因为阻塞或者异常没有发送到发送方。那么这个包会被丢弃,这时接收方会利用其发送窗口发送一个ack包。
4、当应用程序将接收到的数据包读取之后,会将WND加上对应的读取数据包的大小。

滑动窗口的大小
发送窗口的大小要取决于接收窗口,如果发送窗口大于接收窗口的大小,会导致接收窗口无法完全接收数据包,导致一些数据包被丢弃,导致发送窗口的超时重传,浪费资源。

tcp报文头部中有一个window字段,代表着接收窗口的接收数据能力,发送窗口会根据window字段来调整发送窗口大小,保证接收窗口正常接收数据包。

滑动窗口的大小

发送窗口的大小要取决于接收窗口,如果发送窗口大于接收窗口的大小,会导致接收窗口无法完全接收数据包,导致一些数据包被丢弃,导致发送窗口的超时重传,浪费资源。
tcp报文头部中有一个window字段,代表着接收窗口的接收数据能力,发送窗口会根据window字段来调整发送窗口大小,保证接收窗口正常接收数据包。
发送窗口的大小不能超过接收窗口的大小,否则接收窗口不能正常接收数据。

总结

客户端和服务器都各自维护一个发送窗口和发送窗口,用来流水线模式的发送和接收数据。
发送窗口和接收窗口的本质是在操作系统中开辟的一块循环利用的缓冲区,用于存储要发送和接收数据。本质是一个循环数组的实现。利用若干指针来维护相关的区域。当数据写入超过缓冲区的最大地址后,就循环利用头部,覆盖头部的数据。
发送窗口就是一个循环利用的缓冲区,应用层发送数据,就是往缓冲区中写入数据。收到ACK后,就相当于从缓冲区中移除数据,不过并不会真正移除数据,只需要后移对应的指针就可以了。
发送缓冲区分为四个部分:
1、已经收到ack包的数据
已经收到ack包的数据,代表接收窗口已经接收了对应的数据,可以被新数据覆盖。
2、已经发送还未接收到ack包的数据
已经发送出去,但是还未收到接收方对应的ack包
3、允许发送但是还未发送的数据
允许发送但是还未发送的数据。
4、不允许发送的数据。
发送窗口之外的数据,排队等待后续发送。
区间2 和 区间3 构成了发送窗口,两个区间的大小总和对应着发送窗口的大小
接收窗口接收数据包后,会立马返回ack应答包(有序接受的情况),即使应用程序没有读取对应的数据包。
接收窗口也是一个循环利用的缓冲区,接收数据 就是往缓冲区中写入数据。应用层读取数据后,就相当于从缓冲区中移除数据,不过并不会真正移除数据,只需要后移对应的指针就可以了。
接收窗口详情
接收窗口接收数据包后,即使应用程序没有读取对应的数据包,也会立马返回ack应答包,ack应答包中会携带当前接收窗口的大小WND和接收窗口的数据包缓存信息。
1、当数据包的seq == RCV_NEXT的数据包的时候,将接收窗口的RCV_NEXT右移到缓冲区中第一个为空的位置,WND减去对应的移动字节数;
2、当数包的seq > RCV_NEXT 并且 seq < RCV_NEXT+ WND的时候,会将其加入到滑动窗口中对应的位置。
3、如果数据包的seq < RCV_NEXT,说明该数据包已经被接收了,但是对应的ack包因为阻塞或者异常没有发送到发送方。
这时接收方会利用其发送窗口发送一个ack包。
当应用程序将接收到的数据包读取之后,会将WND加上对应的读取数据包的大小。

拥塞控制

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫做网络拥塞。

为什么需要拥塞控制

TCP通过滑动窗口来做流量控制,但是TCP觉得这还不够,因为滑动窗口需要依赖于连接的发送端和接收端,其并不知道网络中间发生了什么。具体一点,我们知道TCP通过一个timer采样了RTT并计算RTO,但是,如果网络上的延时突然增加,那么,TCP对这个事做出的应对只有重传数据,但是,重传会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,于是,这个情况就会进入恶性循环被不断地放大。试想一下,如果一个网络内有成千上万的TCP连接都这么行事,那么马上就会形成“网络风暴”,TCP这个协议就会拖垮整个网络。这是一个灾难。
所以,TCP不能忽略网络上发生的事情,而无脑地一个劲地重发数据,对网络造成更大的伤害。对此TCP的设计理念是:TCP不是一个自私的协议,当拥塞发生的时候,要做自我牺牲。就像交通阻塞一样,每个车都应该把路让出来,而不要再去抢路了

拥塞窗口

发送方维持一个拥塞窗口cwnd的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。同时,发送方让自己的发送窗口等于拥塞窗口。只要网络没有出现拥塞,拥塞窗口就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减少一些,以减少注入到网络中的分组数。

拥塞控制和流量控制的区别

拥塞控制:防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提:网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。

流量控制(滑动窗口就是一种流量控制):指点对点通信量的控制,是端到端的问题。流量控制所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接收

TCP如此可靠,为什么应用层还需要确认机制

在基于进行网络编程时,为了保证消息被对方正常处理 ,会做一个确认机制,那么问题来了,TCP已经有这么多的保证可靠性的操作,为什么我们需要在应用层实现确认机制?
首先明确,在正常情况下,经过调用write方法后,tcp一定能够保证对端能够成功接受到这条TCP消息,但是并不能保证对端的应用层能够正常处理这条消息,也许因为对端应用层的一些逻辑出错,或者其他的一些错误,可能导致这条消息没能被正确处理
因此 TCP的可靠保证的是传输层可靠,至于传输层之上的应用能否正常处理数据包,TCP就无法保证了。需要应用层进行保证。

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

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

相关文章

文件操作相关知识

1、为什么使用文件 前面我们在实现通讯录时&#xff0c;每次运行结束后&#xff0c;我们所存储的数据都会消失。这是因为我们将数据存储在栈区、堆区等内存上&#xff0c;而内存是不具有持久性的&#xff0c;程序退出时&#xff0c;权限还给操作系统&#xff0c;这些数据就会丢…

Unity 3D PC平台发布|| Unity 3D Web 平台发布||Unity 3D Android平台发布

Unity 3D PC平台发布 PC 是最常见的游戏运行平台。 随着欧美游戏的崛起&#xff0c;PC 平台随之发生游戏登陆大潮。 在 PC 平台上发布游戏的步骤&#xff1a; 打开要发布的 Unity 3D 工程&#xff0c;执行 File → Build Settings 菜单命令。在 Platform 列表框中选择 PC&am…

Jenkins, docker-compose动态修改镜像版本升级部署

docker-compose镜像版本动态控制 提取.env文件进行配置通用环境变量 # 当前机器用户的home路径 HOST_HOME/home/guimu # 上传文件临时路径 TMP_DATA_PATH${HOST_HOME}/tempdata/ # media的home路径 MEDIA_HOME/media # 挂载的mysql的data路径 MYSQL_DATA_PATH${HOST_HOME}/my…

go 函数或者方法参数调用的过程

前言 最近做项目&#xff0c;使用go开发&#xff0c;但是在发生函数调用传参数时&#xff0c;对指针的指针的传递有难以理解的代码&#xff0c;就此分析过程。尤其是对于多重指针作为参数&#xff0c;而且对于一些内置函数的修改逻辑也需深入的理解。 1. demo package slice…

client-go源码学习(四):自定义Controller的工作原理、WorkQueue

本文基于Kubernetes v1.22.4版本进行源码学习&#xff0c;对应的client-go版本为v0.22.4 4、自定义Controller的工作原理 Controller中主要使用到Informer和WorkQueue两个核心组件 Controller可以有一个或多个Informer来跟踪某一个resource。Informer跟Kubernetes API Server保…

安装 Visual Studio Code、MinGW-w64、CMake

文章目录1.安装 Visual Studio Code1.1 下载1.2 安装2.安装 MinGW-w642.1 下载2.2 解压到合适的目录下2.3 添加到环境变量2.4 测试是否安装成功3.安装 CMake3.1 下载3.2 解压到合适的目录下3.3 添加到环境变量3.4 测试是否安装成功1.安装 Visual Studio Code 1.1 下载 Visual…

Options API

computed计算属性 1、复杂data的处理方式 我们知道&#xff0c;在模板中可以直接通过插值语法显示一些data中的数据。 但是在某些情况&#xff0c;我们可能需要对数据进行一些转化后再显示&#xff0c;或者需要将多个数据结合起来进行显示&#xff1b; 比如我们需要对多个d…

自动驾驶控制算法之车辆纵向控制(project)

本文为深蓝学院-自动驾驶控制与规划-第二章作业 目录 1 project introduction 2 思路提示 3 解决积分饱和的方法 3.1 IC 积分遇限削弱法 3.2 BC 反馈抑制抗饱和 4 ROSLGSVL联合仿真 1 project introduction 本项目希望大家根据PID控制方法实现一个巡航控制系统。我们已…

深度学习之边缘检测算法论文解读(EDTER: Edge Detection with Transformer)

引言 边缘检测是计算机视觉中最基本的问题之一&#xff0c;具有广泛的应用&#xff0c;例如图像分割[8&#xff0c;23&#xff0c;39&#xff0c;44&#xff0c;45&#xff0c;47]、对象检测[23]和视频对象分割[5&#xff0c;57&#xff0c;59]。给定输入图像&#xff0c;边缘…

webpack-dev-server:静态资源目录配置

目录 webpack-dev-server Webpack项目-配置自动打包 访问错误信息分析 简单配置静态资源访问目录 完整配置静态资源访问目录 directory属性 staticOptions属性 publicPath属性 serveIndex属性 watch属性 完整配置webpack.config.js示例 默认显示index.html内容配置 默…

fsdb DUMP的操作记录

参考链接&#xff1a; https://blog.csdn.net/ohuo666/article/details/124973939https://blog.csdn.net/ohuo666/article/details/124973939 https://blog.csdn.net/yuexiangallan/article/details/121760768https://blog.csdn.net/yuexiangallan/article/details/121760768…

基于 DolphinDB 的行情中心解决方案

随着国内量化金融的高速发展&#xff0c;行情数据所包含的微观交易结构信息越来越受到券商自营团队、资管团队以及各类基金的重视。这些交易团队迫切希望拥有一个与生产环境类似的投研仿真环境&#xff0c;提升研发的效率和质量。作为国内领先的高性能时序数据库厂商&#xff0…

【地铁上的Redis与C#】数据类型(七)--List类型

我们这篇文章开始讲解list类型。 什么是list list是一个存储空间保存多个数据&#xff0c;底层使用双向链表存储结构实现的一种Redis数据类型&#xff0c;。list类型一般用在存储多个数据&#xff0c;并需要对数据进入存储空间的顺序进行区分的情况下。list的存储方式是一个存…

气泡法检漏技术特点分析和新型压力衰减法测试技术

摘要&#xff1a;针对传统的气泡法检漏技术&#xff0c;本文详细介绍了气泡法的基本原理、气泡法中的两种标准方法——加压法和真空法以及对应的标准规范&#xff0c;并对这两种气泡法进行了对比分析。本文还对气泡法的技术特点进行了分析&#xff0c;指出了气泡法检漏技术的局…

使用ruoyi-vue控制数据权限

说在前面 啥是数据权限?例如校长可以看到全部学生的信息,系主任可以看到该院系的学生信息,老师可以看到本班的学生信息,学生自己只能查看自己的信息 对于ruoyi的角色,我们只能控制用户可以访问那些菜单以及接口,而不能控制接口返回的数据 假如有这样一个需求,不同用户上传各…

赛狐ERP | 亚马逊卖家FBA常见问题解析!

许多亚马逊卖家在使用亚马逊FBA时经常会遇到一些问题&#xff0c;如FBA如何收费、如何提升发货数量、物流方式问题等问题&#xff0c;这些问题是常见问题&#xff0c;也是亚马逊卖方们应该把握的问题。下面就来跟大家分享一些常见的亚马逊FBA相关问题。一、亚马逊FBA如何收费&a…

OSCP_vulnhub—GOLDENEYE: 1

vulnhub—GOLDENEYE: 1About信息搜集查看js泄露POP3 密码破解及登录使用admin/xWinter1995x!登录 getshell提权About GoldenEye: 1 ~ VulnHub Download (Mirror): https://download.vulnhub.com/goldeneye/GoldenEye-v1.ova DHCP service: Enabled IP address: Automaticall…

【Kubernetes 入门实战课】Day01——虚拟机创建及安装

文章目录前言一、实验环境选择二、选择合适的虚拟机软件1.VirtualBox2.VMWare三、Linux版本四、如何配置虚拟机1、安装VMware2、虚拟网络设置1、虚拟机网络编辑器2、设置 VMnet 8 网段3、创建虚拟机1、创建虚拟机2、启动虚拟机3、虚拟机配置4、虚拟机管理前言 俗话说&#xff…

[oeasy]python0052_ raw格式字符串_单引号_双引号_反引号_ 退格键

转义字符 回忆上次内容 最近玩的是\n、\r 之外的转义序列 \a是 ␇ (bell)\t是 水平制表符\v是 换行不回车 通过 16 进制数值转义 \xhh把(hh)16 进制对应的 ascii 字符输出 通过 8 进制数值转义 \ooo把(nnn)8 进制对应的 ascii 字符输出 这次加了 转义输出 反斜杠本身 \\ 输出…

24.Isaac教程--路径规划的区域划分

路径规划的区域划分 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 为了赋予地图区域关于通过它们规划的路径的语义意义&#xff0c;引入了三个新的规划器影响区域&#xff1a; No-replanning zones&#xff1a;当机器人通过这个多边形区域时&a…