【网络基础】TCP协议2

TCP建立连接

什么是TCP连接

用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket、序列号和窗口大小称为连接。
Socket:由 IP 地址和端口号组成
序列号:用来解决乱序问题等
窗口大小:用来做流量控制

三次握手作用

  1. 建立连接
  2. 协商起始序列号
  3. 协商双方的接收缓冲区大小

三次握手的过程

在这里插入图片描述

  1. 第一次握手:客户端发送一个SYN到服务器请求建立连接,这个SYN包含一个序列号(用于在后续的数据传输中进行标记),客户端进入SYN_SENT状态,等待服务器响应。
  2. 第二次握手:服务器收到SYN包后,捎带应答一个SYN+ACK(确认应答序列号+1)给客户端(包含服务器自己的序列号),服务器进入SYN_RECV状态,等待服务器响应。
  3. 第三次握手:客户端收到SYN+ACK后,发送一个ACK确认应答。这个ACK包包含对服务器的应答,即客户端确认应答序列号+1。客户端发送后状态变为ESTABLISHED,服务端收到报文后也变为此状态。

为什么是三次握手?

能防止历史连接的建立,能减少双方不必要的资源开销,能帮助双方同步初始化序列号。
奇数次握手,可以确保一般情况握手失败的连接成本嫁接在客户端上。验证全双工的最小次数。
不是两次?
连接失败的成本会嫁接到服务端,无法防止历史连接的建立,会造成双方资源的浪费,也无法可靠的同步双方序列号。
不是四次?
三次握手就已经理论上最少可靠连接建立,所以不需要使用更多的通信次数。
不是一次?
服务端接收到客户端的 SYN 包就认为建立连接成功的话,这样会带来 SYN 洪水攻击问题。

accept的第二个参数backlog

backlog+1表示底层已经建立好连接队列的最大长度。当服务器一个连接建立完成(即进入ESTABLISHED状态),当服务端没有调用accept函数,该连接便会进入该队列等待。如果队列已满,服务端收到连接后进入SYN_RECV状态(半连接状态)放入半连接队列,服务器不会长时间维护此状态,一定时间会丢弃。

TCP断开连接

四次挥手过程

在这里插入图片描述

  1. 第一次挥手:客户端主动向服务端发送FIN报文,请求断开连接(客户端进入FIN_WAIT_1状态),表明客户端不会再向服务端发送数据(但可以接受服务端发来的数据)。
  2. 第二次挥手:服务端接收到FIN报文后,会发送ACK报文(进入CLOSE_WAIT状态),表明服务端收到了客户端的FIN。而服务端可能还有数据需要进行处理和发送,连接并没有真正关闭。(客户端收到ACK进入FIN_WAIT_2状态)
  3. 第三次挥手:服务端处理完数据,发送FIN报文给客户端。(服务端变为LAST_ACK)
  4. 第四次挥手:客户端收到FIN报文后(状态变为TIME_WAIT),向服务端发送ACK报文,表明确认连接关闭。(服务端收到ACK报文后,状态变为CLOSED)
  5. 主动关闭连接的一方进行第四次挥手后,需要维持一段TIME_WAIT状态一段时间(报文最大生存时间)然后进入CLOSE状态。

TIME_WAIT状态

主动断开连接的一方会进入TIME_WAIT状态,该状态时连接没有彻底断开,ip和port正在被使用,无法立即重启。

setsockopt设置套接字能被复用

在这里插入图片描述

为什么 TIME_WAIT 等待的时间是 2MSL?

MSL 是 Maximum Segment Lifetime,报文最大生存时间,即报文从一端到另一端所需时间的最大值。它是任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃。
让通信双方历史数据得以消散。让断开连接时4次挥手有较好的容错性(即如果最后一次ACK丢失,客户端在TIME_WAIT还可以重发)。
如果客户端(主动关闭放)最后一次 ACK 报文(第四次挥手)在网络中丢失了,那么根据 TCP 可靠性原则,服务端(被动关闭方)会重传 FIN 报文。假设客户端(主动关闭连接放)没有 TIME_WAIT 状态,而是在发完最后一次 ACK 报文就直接进入 CLOSED 状态。如果该 ACK 报文丢失了,服务端则重传 FIN 报文,而此时客户端已经进入关闭状态了,在收到服务端重传的 FIN 报文后,就会回复 RST 报文。
在这里插入图片描述
服务端收到这个 RST 并将其解释为一个错误(Connection reset by peer),这对于一个可靠的协议来说不是一个优雅的终止方式。
为了防止这种情况出现,客户端必须等待足够长的时间,确保服务端能够收到 ACK,如果服务端没有收到 ACK,那么就会触发 TCP 重传机制,服务端会重新发送一个 FIN,这样一去一来刚好两个 MSL 的时间。
在这里插入图片描述

流量控制

TCP流量控制基于接收方的实际接收能力。在数据传输过程中,接收方会根据其缓冲区的大小和当前的网络状况,通过发送确认信号(ACK)来通知发送方可以发送的数据量。发送方则根据接收方的确认信号来控制其数据发送速率,确保发送的数据量不会超过接收方的处理能力。

  • 接收端将自己接收缓冲区剩余空间的大小放入 TCP 报头中的窗口大小字段,通过 ACK 报文通知发送端。
  • 窗口大小字段越大,说明网络的吞吐量越高。
  • 接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端。发送端接受到这个窗口之后,就会减慢自己的发送速度。
  • 如果接收端缓冲区满了,就会将窗口大小置为0。这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收端把窗口大小告诉发送端。还有一种策略就是,接收端的缓冲区剩余空间更新后,接收端会给发送端发送窗口更新通知来告知对方接收缓冲区剩余空间的大小。
  • TCP 是全双工的,可以在两个方向上进行流量控制。 三次握手时,会通过 TCP报头中的窗口大小字段来告知对方自己的接收缓冲区剩余空间的大小。那么在正式进行网络通信时,就已经得知对方的接收能力了,可以根据对方的接收能力来发送数据。
  • 16位窗口字段最大能表示的值是 65535,那么 TCP 窗口最大就是 65535 字节么?并不是,实际上,TCP 报头 40字节选项中还包含了一个窗口扩大因子 M,实际窗口大小是窗口字段的值左移 M 位,M 的取值范围是 0 到 14。

滑动窗口

TCP滑动窗口是一种动态窗口,它的大小可以在一定范围内进行调整。发送方和接收方都维护一个窗口,窗口的大小决定了在无需等待对方确认的情况下,可以连续发送数据包的最大数量。

在这里插入图片描述

工作原理

TCP滑动窗口以字节为单位,分为发送窗口和接收窗口。发送方在发送数据时,会根据接收方的窗口大小来确定发送的数据量。当发送方发送一个数据包后,它会等待接收方的确认(ACK)报文。如果接收方成功接收了数据包并返回了ACK报文,那么发送方的滑动窗口就会向右滑动一格,继续发送下一个数据包。如果发送方在一段时间内没有收到接收方的ACK报文,那么它会认为数据包丢失,并启动超时重传机制。
在这里插入图片描述
如上图当发送端收到ACK2001后就向右滑动,滑动窗口大小表示无需等待 ACK 应答而可以继续发送数据的数量的最大值。大小是动态变化的。

  • 右不变,左移动,窗口变小:对方应用层没有从tcp接收缓冲区拿数据。
  • 左右都移动,整体的范围扩大/变小
    start=确认序号
    end=确认序号+窗口大小
    滑动窗口一直向右移动并不会造成越界问题。因为发送缓存区是被看成环形队列的,当滑动窗口向右移动时,如果超出了缓冲区的范围,那么就会进行模除运算,重新回到缓冲区的起始位置进行向右移动。

丢包问题

情况一.ack丢失

  • 允许少量的ack丢失,因为确认序号表示序号之前的报文都已经被接收。例如:当3000-4000丢失,3000-4000的应答报文中确认序号仍然是3001,4000-5000的报文中也是3001。

情况二.数据丢失

在这里插入图片描述
当1001-2000的报文丢失,主机A收到三次相同的确认应答,那就会触发快重传机制。
为何还需要超时重传?
快重传有条件的(必须三次一样的确认应答)才能触发,如果报文是最后一个或者倒数第二个就不满足快重传条件。超时重传作为一个兜底策略,而快重传是为了提高效率。

拥塞控制

如果通信双方出现了大量的数据丢包(超时)问题,tcp会判断网络出问题了(网络拥塞)。此时不能立即对报文进行超时重传。tcp协议是多主机在网络出现拥塞时达成共识

解决方案

TCP引入慢启动机制,先发少量数据探探路,如果得到应答,再慢慢增大数据量。
引入拥塞窗口概念,初始值为1,每次收到一个ack,拥塞窗口+1,每次发送数据包时,将拥塞窗口和接收端反馈的窗口大小(前文认为的滑动窗口大小)作比较,取最小值最为实际发送的大小。
在这里插入图片描述

  • 拥塞窗口:主机判断网络健康状态的指标,超过拥塞窗口大小,会引发网络拥塞。
    在这里插入图片描述
  • 指数增长:刚开始发送数据时,拥塞窗口大小被设置为 1,并且以指数形式进行增长。因为指数前期增长较慢,可以避免网络拥塞问题。而中后期时指数增长快,此时网络也恢复了,可以尽快恢复双方的通信效率。
  • 线性增长:慢启动的阈值初始时被设置为对方窗口大小的最大值,上图中的慢启动阈值为 16。当拥塞窗口的大小增长到慢启动阈值时就不再以指数形式进行增长,而采用线性增长的方式。注意:线性增长阶段时,还未发生网络拥塞问题。
  • 乘法减小:当拥塞窗口大小增长到 24 时,发生了网络拥塞问题,此时慢启动阈值就会变成当前拥塞窗口大小的一半,同时拥塞窗口大小变成一。然后拥塞窗口再次以指数的形式进行增长,周而复始。

应答

延迟应答

接收端在处理完多个数据包后再发送ACK应答,从而增大了滑动窗口的大小,提高了数据传输的效率。

  • 假设接收端缓冲区为 1M,一次收到了 500K 的数据。如果立刻进行应答,那么返回的窗口大小就是 500K。
  • 但实际上接收方处理数据的速度可能会很快,10ms 之内就可以把 500K 数据从缓冲区消费掉了。
  • 在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来。
  • 如果接收端稍微等一会再应答,比如等待 200ms 再应答,那么这个时候接收方返回的窗口大小就是 1M。
  • 数量限制:每隔 N 个包就应答一次。
  • 时间限制:超过最大延迟时间就应答一次(这个时间不会导致超时重传)

捎带应答

TCP 协议的捎带应答机制就是发送的同一个 TCP 数据包中即包含数据又包含 ACK 应答的一种机制。

小结

可靠性

  • 检验和
  • 序列号(按序到达+去重)
  • 确认应答
  • 超时重发
  • 连接管理
  • 流量控制
  • 拥塞控制

提高性能

  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答
  • 流量控制

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

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

相关文章

运维别卷系列 - 云原生监控平台 之 04.prometheus 查询语句 promql 实践

文章目录 [toc]PromQL 简介什么是时间序列 PromQL 数据类型即时向量 Instant vector范围向量 Range vectorTime DurationsOffset modifier modifier 浮点值 Scalar字符串 String PromQL FUNCTIONSfloor()irate()rate()round()sort()sort_desc() PromQL 运算符算术运算符比较运算…

Go vs Rust:哪种编程语言更好,为什么?

在开始前我有一些资料,是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!! Go 和 Rust 都是现代编程语言&…

【数据结构】堆(超详细)

文章目录 前言堆的概念及结构堆的实现堆的向下调整算法(建小堆为例)堆的向上调整算法(建小堆为例)堆的初始化销毁堆堆的插入堆的删除(规定删堆顶的数据)取堆顶元素判断堆是否为空获取堆的个数 完整代码(包括测试代码&a…

【计算机毕业设计】基于SSM++jsp的高校专业信息管理系统【源码+lw+部署文档+讲解】

目录 第1章 绪论 1.1 课题背景 1.2 课题意义 1.3 研究内容 第2章 开发环境与技术 2.1 MYSQL数据库 2.2 JSP技术 2.3 SSM框架 第3章 系统分析 3.1 可行性分析 3.1.1 技术可行性 3.1.2 经济可行性 3.1.3 操作可行性 3.2 系统流程 3.2.1 操作流程 3.2.2 登录流程 3.2.3 删除信息流…

springboot通过 EasyExcel.read()方法解析csv(excel)文件中的数据用list接收

springboot通过 EasyExcel.read()方法解析csv(excel)文件中的数据用list接收 文章目录 前言一、EasyExcel是什么?二、使用步骤1.引入库2.接收数据的实体类3.处理字典值ExcelDictConverter4.把文件中的数据解析出来放入…

Java面试八股之一个char类型变量能不能存储一个中文字符

Java中一个char类型变量能不能存储一个中文字符?为什么? Java中一个char类型变量可以存储一个中文字符。原因如下: Unicode编码支持:Java语言采用Unicode字符集作为其内建字符编码方式。Unicode是一种广泛接受的字符编码标准&am…

摸鱼大数据——Linux搭建大数据环境(集群免密码登录和安装Hadoop)二

集群设置免密登录 克隆node1虚拟机的前置条件:node1虚拟机存在且处于关闭状态 1.克隆出node2虚拟机 1.node1虚拟机: 右键 -> "管理" -> "克隆" 2.图形化弹窗中: "下一页"->"下一页"->选择"创建完整克隆&…

简单问题汇总

一、vector和list 1.vector vector是可变大小数组的序列容器,拥有一段连续的内存空间,并且起始地址不变,因此能高效的进行随机存取,时间复杂度为o(1);但因为内存空间是连续的,所以在进行插入和删除操作时…

本地运行《使用AMD上的SentenceTransformers构建语义搜索》

Building semantic search with SentenceTransformers on AMD — ROCm Blogs 这篇博客解释了如何在Sentence Compression数据集上训练SentenceTransformers模型来执行语义搜索。使用BERT基础模型(不区分大小写)作为基础的变换器,并应用Huggi…

GPT-4o:全面深入了解 OpenAI 的 GPT-4o

GPT-4o:全面深入了解 OpenAI 的 GPT-4o 关于 GPT-4o 的所有信息ChatGPT 增强的用户体验改进的多语言和音频功能GPT-4o 优于 Whisper-v3M3Exam 基准测试中的表现 GPT-4o 的起源追踪语言模型的演变GPT 谱系:人工智能语言的开拓者多模式飞跃:超越…

Threejs 学习笔记 | 灯光与阴影

文章目录 Threejs 学习笔记 | 灯光与阴影如何让灯光照射在物体上有阴影LightShadow - 阴影类的基类平行光的shadow计算投影属性 - DirectionalLightShadow类平行光的投射相机 聚光灯的shadow计算投影属性- SpotLightShadow类聚光灯的投射相机 平行光 DirectionalLight聚光灯 Sp…

生活服务商家拥抱数字化,鸿运果系统加速“服务生意数字化”进程

在数字化转型的大潮中,生活服务商家正积极拥抱变革,以适应新的市场环境和消费者需求。鸿运果系统作为专业的“服务生意”数字化解决方案提供商,正助力商家加速数字化转型,推动行业向智能化、个性化服务转型。 数字化转型的背景 …