传输层协议TCP

一.TCP协议格式

对于传输层协议我们之前是学过了UDP,对于传输层协议是存在了一定的了解的,所以现在我们再来看TCP协议格式:

我们之前学过UDP的报文格式,所以源端口和目的端口是不需要进行再次讲解的,对于32序号和确认序号目前我们是先无法学懂的,所以我们可以先将目光焦距到保留六位---即6个标志位:

URG: 紧急指针是否有效
ACK: 确认号是否有效
PSH: 提示接收端应用程序立刻从 TCP 缓冲区把数据读走
RST: 对方要求重新建立连接; 我们把携带 RST 标识的称为复位报文段
SYN: 请求建立连接; 我们把携带 SYN 标识的称为同步报文段
FIN: 通知对方, 本端要关闭了, 我们称携带 FIN 标识的为结束报文段

后续我们可以对他们进行详细讲解,所以这里先大概了解下是哪6个即可!

16 位校验和: 发送端填充, CRC 校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含 TCP 首部, 也包含 TCP 数据部分
4 位 TCP 报头长度: 表示该 TCP 头部有多少个 32 位 bit(有多少个 4 字节); 所以TCP 头部最大长度是 15 * 4 = 60

16 位紧急指针: 标识哪部分数据是紧急数据
下面我们会来一一详细讲解



二.三大机制

1.确认应答机制

也叫ACK,在TCP传输的数据中,TCP会对每个数据字节进行编号,称为序列号,而在每次reponse时,ACK都会携带确认序号,如上图中的确认序号,例如:在收到的报文序号为2000,那么响应报文中的确认序号就是2001(前提中间未发生丢包)

确认序号的意义:告诉发送者自己已经收到了那些数据,并且下次从哪个位置发送信息

2.超时重传机制

当我们发送的数据包在网络传输过程中丢失,此时就需要将数据包重新发送,中间需要一个特定的时间间隔,方便确认是否需要重传

注意点:超时重传机制的判断是通过是否收到ACK应答,如果ACK应答丢失,是不会重发ACK应答的,该部分不属于超时重传机制,超时重传机制是针对发送方的

如果是ACK丢失,发送方在规定的时间间隔中就会重新发送数据包,然后等待ACK确认,但是大家要清楚的是我们有确认序号,TCP 协议能够识别出那些包是重复的包, 并且把重复的丢弃掉,并且我们可以利用前面提到的序列号, 就可以很容易做到去重的效果

现在问题来了:这个时间间隔我们如何确定呢?

大家都知道网络是存在波动的,高峰期显然传输需要时间更长,低谷期显然传输效率更快,那么一个合适的时间非常重要,此时TCP使用了动态时间设置,下面我们以linux为例:

当我们第一次发送数据未收到ACK响应时,以500ms位单位,重发一次,再无法收到响应时,以500ms*2为时间间隔,第三次仍未收到响应时,时间间隔为500ms*4,后面依次类推,500ms*2的n-1次方,直到累计到一定次数,TCP认为网络出现拥塞,进行拥塞等待,当然也可能是主机出现问题,关闭连接

3.连接管理机制

对于该机制,我们主要就是讲解大家可能都听过的三次握手和四次挥手

三次握手:

我们首先来先了解下tcp协议中的保留位:

我们知道ACK是应答,那么其他5位呢?

SYN:是指请求建立连接

FIN:是指请求断开连接

URG:确认紧急指针是否有效(后序会讲解紧急指针)

PSH:提示接收端程序从tcp缓冲区中将数据取走

RST:对方要求重新建立连接; 我们把携带 RST 标识的称为复位报文段

要注意的是:对于上面6位,如果对应位置设置为1表示该符号位生效,否则为0

如果此时被问起为什么需要保留位,相信大家答案就非常明确了,因为只有知道不同报文的作用才能知道处理什么问题

现在我们可以来讲解三次握手,如下图:

我们联系之前学过的知识,现在来仔细理解下三次握手:

最开始时,客户端和服务端同时处于CLOSED状态,然后客户端想要建立连接,通过socket函数生出fd,然后通过connect(fd,服务器端口)开始连接服务器,与此同时,服务器从CLOSED状态通过socket函数同样得到一个fd,称之为listenfd,然后bind(listernfd,自身端口号),接下来通过listen函数保持监听状态,当客户端发送的SYN包到达服务器时,调用accept函数,将自身状态转换为SYN_RCVD,然后向客户端发送响应包ACK和建立连接的请求SYN,当connect函数收到ACK+SYN时,将SYN_SENT状态转换为ESTABLISHED,同时再次发送响应报文ACK,接下来服务器收到ACK后,也将自身状态转换为ESTABLISHED,同时accept函数返回分配新的描述符,开始双方通信

现在问题来了,为什么不是两次建立连接呢?即客户端收到ACK就直接建立连接,不需要再次发送ACK到服务端?

假设我们第一次发送的SYN在传输过程中发送阻塞,然后客户端第二次发送SYN,如果客户端收到发送ACK给客户端,两者直接建立

为什么不是四次连接呢?

我们发现三次连接就可以确定连接是否建立好,所以完全不需要浪费效率

现在我们要重点知道的是:如果某次传输中丢失数据会如何?

当客户端第一次发送SYN丢失时,相当于连接请求丢失,在一定的时间间隔后会重新发送请求,后面我们会对时间间隔进行详细讲解

当服务端的响应报文SYN+ACK丢失时,在一定的时间内客户端未收到响应报文,会再次重发SYN,当服务端收到SYN时,重新发送响应数据,从而直到客户端收到

客户端收到响应数据后,发送ACK响应服务端,如果该响应在传输中丢失,那么服务器就会重新发送SYN+ACK响应数据,此时客户端收到该响应数据时就会知道刚才发送的数据ACK丢失,重新发送,从而确认连接成功建立

以上就是tcp三次握手的过程,下面我们来讲解四次挥手:

如上图(自己画的不标准请见谅)

下面我们先来讲解具体过程:

1.当客户端(两台中任意一台)主动申请断开连接,会响服务端发送一个FIN数据,并且将自身established状态改变成为FIN_WAIT_1

2.当服务端收到客户端发送的FIN数据后,服务端发送ACK响应报文,并且将自身状态改变成为CLOSED_WAIT状态

3.当客户端收到响应报文,将自身状态变成FIN_WAIT_2,等待服务端结束报文

4.服务端调用close函数,向客户端发送一个FIN,表示断开连接,然后将自身状态变成LAST_ACK,等待客户端最后一个ACK到来

5.客户端收到FIN数据后,将自身状态变成TIME_WAIT,然后发送响应报文ACK

6.服务端收到响应报文后,将服务器对应closed,客户端在等待2msl后,也closed

下面我们再来讲解下如果中间某个过程数据在传输过程中丢失该如何解决:

我们将上图中四个发送红线分为四个步骤:

1.该步骤数据丢失时,即服务器未收到FIN,在一定的时间间隔客户端未收到响应数据,会重新发送FIN

2.该步骤丢失(即ACK响应报文丢失),还是客户端收不到响应报文,结果如上1

3.客户端发送的FIN在传输过程中丢失,在规定的时间间隔中未收到ACK响应,会重新发送FIN

4.ACK丢失,服务端重复步骤3

以上就是四次挥手过程



三.相关时间概念

上面我们多次提到了时间间隔,现在我们就对上面内容进行时间上知识的补充

上面我们是写过一个时间2MSL,MSL是指maximum segment lifetime,在网络通信过程中规定主动断开连接的一方处于TIME_WAIT,然后等待2MSL才能进入CLOSED状态。

其中MSL是指tcp报文最大生存时间,这样如果我们将等待时间确认为2MSL的话,在双方向的数据传输就会保证全部传输结束,同时也是在理论上保证最后一个报文可靠到达(假设最后一个 ACK 丢失, 那么服务器会再重发一个 FIN. 这时虽然客户端的进程不在了, 但是 TCP 连接还在, 仍然可以重发 LAST_ACK

现在大家发现一个问题没?如果我们终止一个tcp连接方,在2MSL时间内是无法使用该对象的端口号的,这也是说明了进程结束但是tcp连接不是立即断开的

关于MSL具体是多少时间,在不同的系统上是不一样的,Linux-centos7上是指1min

下面我们来看这么一个问题:

如果一个服务器需要短时间内处理大量的客户端连接,如果是服务端主动断开连接,那么就会存在大量的TIME-WAIT,每个连接都会占用一个通信五元组(源 ip, 源端口, 目的 ip, 目的端口, 协议). 其中服务器的 ip 和端口和协议是固定的. 如果新来的客户端连接的 ip 和端口号和 TIME_WAIT 占用的链接重复了, 就会出现问题,那么这个问题如何解决呢?

我们可以使用setsockop()解决问题,如下:

setsockopt()设置 socket 描述符的 选项 SO_REUSEADDR 为 1, 表示允许创建端
口号相同但 IP 地址不同的多个 socket 描述符

至于我们网络丢包的时间间隔大体和MSL相似,也是网络的一个设置,可以固定一个时间,便于我们网络传输
 



四.滑动窗口和流量控制

该滑动窗口可不是之前我们算法中的内容,对于TCP滑动窗口大家需要重新学习:

在上面我们讲解了确认应答机制,但是大家可能会发现如果我们是一发一收的方式效率太低了,那么有没有其他办法提高效率呢?

是的,存在的,tcp给出了滑动窗口的方式解决该方案效率低下问题,具体如下:

我们现在假设一次发送多个数据,然后服务端并不是每次都响应,从而实现多发一送的方式,这样就提高了效率,但是我们如何确认数据传输中有没有数据丢失呢?

现在我们来具体来看看滑动窗口的实现,再来解决上面这个问题:

假设我们数据每次传输1000字节,然后4次一起传输,不需要等待ACK,当我们4个数据都发送完,可能会收到第一个ACK,这样通过ACK中的确认序号,如果确认序号的数字不是4001,说明接收端的内容在某处传输失败,这样通过窗口移动,从失败位置再次发送四个数据,如果发送的数据没收到ACK,这样发送端重新发送内容即可,这样就可以实现滑动窗口发送信息,提高效率

我们都知道tcp是存在发送缓冲器和接收缓冲区的,现在我们就可以来理解为什么需要发送缓冲区了?

你可能会认为是为了提高传输效率,当然这是一个原因,但不是主要的,实际上主要还是为了编号,联系上面我们学的滑动窗口,我们知道传输是按照一定的编号的,因此我们需要再发送缓冲区对数据字节编号,这样方便定位和发送

下面我们思考下面两个传输丢包问题:

1.如果ACK丢失,该如何解决?

我们知道ACK是为了确认信号给发送方,也就是说如果这次tcp发送方未收到另一方的ACK应答,可以继续发送后面一个窗口的内容,当下一次的ACK收到后,我们只需要查看确认报文是否与发送缓冲区最后对应的序号相同即可

2.如果发送的数据包丢失,该如何解决?

很显然这是一个不得不处理的问题,但是实际上处理方式还是和我们想象的不一样的,当ACK表示存在丢包问题后,发送方不会立即处理该问题,而是继续发送后面的窗口内容,当连续收到三次ACK都表示存在该问题后,才会去窗口移动的确认报文位置处理该问题,这种机制称为高速重发机制

下面我们来讲讲另一个话题:流量控制

接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应,此时就需要我们处在一个机制来控制这种情况,这就是流量控制,定义:通过接收端的处理能力, 来决定发送端的发送速度的机制
那么该机制是如何实现的呢?

具体如下:

接收端将自身缓冲区大小通过ACK发送给发送方,这也是我们TCP协议格式中窗口大小需要填写的内容,这样发送发就可以知道对方的接收能力,从而控制,当接收缓冲区快满时(也可以到达一定程度时),ACK应答会改变窗口数据大小,从而使发送方减少窗口大小,当接收方缓冲区内容减少到一定程度后,又会增大ACK中窗口数据大小,这就是流量控制

特殊情况:

如果接收端缓冲区满了, 就会将窗口置为 0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端
补充知识:我们知道tcp数据格式中窗口大小是有一个 16 位窗口字段,那么问题来了, 16 位数字最大表示 65535, 那么 TCP 窗口最大就是 65535 字节么?
实际上, TCP 首部 40 字节选项中还包含了一个窗口扩大因子 M, 实际窗口大小是 窗口字段的值左移 M 位



五.拥塞控制

我们知道网络在传输过程中共同用一个网络,所以网络的拥塞情况非常重要,TCP为了解决该问题,引入了慢启动机制,简单来说就是如果我们在连接刚建立的时候就发送大量数据时非常容易发送拥塞的,导致传输失败等情况,而TCP在连接刚建立的时候先通过发送少量的数据来探测网络情况,这样就可以情况来控制传输速度

具体是如何实现的呢???

我们可以来这样理解,我们定义一个概念:拥塞窗口

当TCP连接建立后,发送方将拥塞窗口设置为1,然后当收到一个ACK后,就将拥塞窗口大小+1,当下次发送时,比较拥塞窗口和接收端主机反馈的窗口大小, 取较小的值作为实际发送的窗口,通过这样的方式,实现了慢启动,但是增长速度快的方式

再引入一个叫做慢启动的阈值,当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长
具体如下图所示:



六.延迟应答和捎带应答

首先我们先来讲解下什么是延迟应答?

来看下面这个问题?

我们知道接收缓冲区的存在,现在我们假设其大小为1M,而接收端能够在200ms处理500K,现在我们如果接收端收到数据后立即就换回窗口大小,即500K,那么接收的数据就会显得有点小,但是如果我们延迟200ms应答返回ACK,这样就可以将窗口大小设置为1M

这样网络吞吐量就越大, 传输效率就越高. 而我们的目标是正是在保证网络不拥塞的情况下尽量提高传输效率;
但是这也不意味着所有的包都可以延迟应答,需要看时间处理

下面我们再来看看捎带应答:

捎带应答就非常好理解了,我们将发送的信息和响应一起发送回去就可以看成是一次捎带应答



最后我们来进行TCP和UDP对比:

TCP 是可靠连接, 那么是不是 TCP 一定就优于 UDP 呢? TCP 和 UDP 之间的优点和缺点, 不能简单, 绝对的进行比较:
TCP 用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景;
UDP 用于对高速传输和实时性要求较高的通信领域, 例如, 早期的 QQ, 视频传输等. 另外UDP 可以用于广播;
归根结底, TCP 和 UDP 都是程序员的工具, 什么时机用, 具体怎么用, 还是要根据具体
的需求场景去判定

以上就是TCP全部内容,感谢大家的支持!!!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习笔记024——Ubuntu 安装 Redis遇到相关问题

目录 1、更新APT存储库缓存: 2、apt安装Redis: 3、如何查看检查 Redis版本: 4、配置文件相关设置: 5、重启服务,配置生效: 6、查看服务状态: 1、更新APT存储库缓存: sudo apt…

C++为函数提供的型特性——缺省参数与函数重载

目录 一、缺省参数 二、函数重载 一、缺省参数 C为函数提供了一项新的特性——缺省参数。缺省参数指的是当前函数调用中省略了实参自动使用的一个值。这极大地提高了函数的灵活性 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值 。在调⽤该函数时,如果没有…

前端框架Vue3基础部分

什么是Vue? Vue是一个能用于构建用户交互页面(动态网页)的渐进式JavaScript框架,易学易用,性能出色,适用性强的Web前端框架。 Vue的设计模式? Vue的设计模式:MVVM模式 MVVM设计模…

安达发|APS自动排程软件异常预警处理场景介绍

APS生产排单软件通过预先设定好相关基本资料与约束规则,当订单、机台、工具、材料、上下班时间等任何影响生产计划的因素变化后,只需执行“一键式排程计算”,系统即可生成相应的生产计划。它不仅能够高效地安排生产任务,优化资源分…

在阿里云快速启动Appsmith搭建前端页面

什么是Appsmith Appsmith是一个开源的低代码开发平台,它使得开发者能够快速地构建内部工具、业务管理系统、CRM系统等。Appsmith通过提供一系列预建的UI组件(如表格、图表、表单等),以及对数据库、API调用的直接支持,…

命令执行简单(棱角社区有毒)

前言:小迪安全2022第一节反弹shell,小迪用的是两台都是云服务器,没有服务器可以在自己的主机上搭建也是可以的,主机上搭两个网站 思路:生成一个木马文件,下载到本机,然后利用本机上传到目标主机…

基于Ruoyi的同一token跨系统访问,后端单点登录并且鉴权方案

基于Ruoyi的同一token跨系统访问,后端单点登录并且鉴权方案 需求场景以及先决条件默认方案改造思路改造代码,一共4个类需要变更完整需要修改的代码 需求场景以及先决条件 同一环境下的多个ruoyi项目,各自使用相同的一组用户(我这里用的是LDAP的登录,不影响本文),但是每个权限拥…

图像/文字差异类型验证码识别 无需训练

某像差异在个别全家桶验证方便有使用,对于这种验证码类型如下: 首先还是目标检测,直接用 dddd 自带的detection 就足够了。 特征提取 其次经过观察,差异答案与其他三个无非就是颜色,字体,方向&#xff0c…

【AI+教育】一些记录@2024.11.16

《万字长文,探讨关于ChatGPT的五个最核心问题》 万字长文,探讨关于ChatGPT的五个最核心问题关于 ChatGPT 铺天盖地的信息让人无所适从。本文则试图提炼出五个关键问题:如何理解这次范式突破,未来能达到的技术天花板,行…

Java-04 深入浅出 MyBatis - SqlSessionFactory 与 SqlSession DAO与Mapper 代理模式

点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatis&#xff…

在Unity中使用Epplus写Excel

Overview 本文旨在帮助你快速入门,该库发展多年内容庞大(官方文档写的极好:https://github.com/EPPlusSoftware/EPPlus/wiki),有些功能在Unity环境可能你永远都不会使用. 官方的一个Demo: https://github.com/EPPlusSoftware/EPPlus.Samples.CSharp 如果你只有读的需求,可以…

leetcode 删除有序数组的重复项

26. 删除有序数组中的重复项 已解答 简单 相关标签 相关企业 提示 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 n…

HNUST-党校培训自动下一集油猴脚本

1.起初 好烦,这个系统看视频需要一直点按键,还没有自动下一集的功能,于是就有了这个js代码 2.效果 实现自动点击是否观看,检测按键自动播放下一集 3.代码(你需要下载油猴,打开管理面板,新建代码) // UserS…

深入了解 GIS 地理信息系统和前端五大 GIS 技术,GIS地理信息系统介绍及前端五大 GIS 技术解析

目录 前言 地理信息系统 (GIS) 是现代数据化社会的重要工具,广泛应用于智慧城市、环境保护、交通管理等领域。随着 Web 前端技术的发展,GIS 可视化在浏览器端的表现能力越来越强,成为许多开发者关注的焦点。这里分享记录 GIS 的基础知识&am…

美团单车上线暖手套,美团贴心服务会给市场带来什么?

首先,美团单车上线暖手套这一举措主要是为了提升市民在秋冬季节骑行共享单车、电单车的出行体验。这一贴心的设计能够解决骑行者在寒冷天气中手部受冻的问题,使得骑行更加舒适和安全。 其次,美团的这一贴心服务会对市场产生积极影响。一方面…

Mysql-DQL语句

文章目录 DQL 语句简单查询查询表所有数据查询指定列 别名查询清除重复值查询结果参与运算 🏡作者主页:点击! 🤖Mysql专栏:点击! ⏰️创作时间:2024年11月16日11点39分 DQL 语句 DQL 语句数据…

【cpp中的继承】

什么是继承? 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构&…

iOS 18 导航栏插入动画会导致背景短暂变白的解决

问题现象 在最新的 iOS 18 系统中,如果我们执行导航栏的插入动画,可能会造成导航栏背景短暂地变为白色: 如上图所示:我们分别向主视图和 Sheet 弹出视图的导航栏插入了消息,并应用了动画效果。可以看到,前者的导航栏背景会在消息插入那一霎那“变白”,而后者则没有任何…

《Java核心技术 卷I》Collection接口和迭代器

Collection接口 Java类库中&#xff0c;集合类的基本接口是Collection接口&#xff0c;两个基本方法&#xff1a; public interface Collection<E>{boolean add(E element);Iterator<E> iterator();...... } add方法用于向集合中添加元素&#xff0c;如果元素确…

《Python制作动态爱心粒子特效》

一、实现思路 粒子效果&#xff1a; – 使用Pygame模拟粒子运动&#xff0c;粒子会以爱心的轨迹分布并运动。爱心公式&#xff1a; 爱心的数学公式&#xff1a; x16sin 3 (t),y13cos(t)−5cos(2t)−2cos(3t)−cos(4t) 参数 t t 的范围决定爱心形状。 动态效果&#xff1a; 粒子…