【TCP 协议】确认应答机制 超时重传 三次握手 四次挥手
TCP报文首部
确认应答机制
TCP 是可靠的,指的是它能够确保数据从源端准确无误地传输到目的端。
当客户端和服务器通信时,客户端向服务器发送报文,那么,客户端怎么知道服务器已经收到报文了呢?
服务器收到客户端发的报文后,对收到的报文做出应答,也就是说,服务器向客户端发送应答报文,这样客户端就可以知道服务器收到自己发送的报文了,如果客户端没有收到服务器发来的应答,说明自己发送的报文丢包了,或者服务器发的应答报文丢包了,此时客户端重新把该报文发给服务器,这样就可以保证 TCP 的可靠性。就像在日常生活中,我问朋友 “吃了吗”,朋友回复 “吃了”,我根据朋友的回答,就可以知道朋友听到了我说的话,如果朋友没有回复,我就再问朋友一次。
那么服务器怎么知道客户端收到了应答呢?即,需要对应答做应答吗?
客户端也可以针对服务器的应答报文发送应答,但是这样就陷入死循环了,双方不断地对应答作出应答,所以 TCP协议规定,当 接收方 发送应答给 发送方,以确认 接收方 已经成功接收到数据段时,发送方 不需要再回送一个确认来确认自己收到了这个应答。即,不需要再对应答做应答!
不需要对应答做应答,意味着虽然应答的发送方无法确认应答的接收方是否接收到了应答,即无法确认最新的报文(绿色箭头)的可靠性,但是可以确认的是,最新的报文之前的报文,即历史上发送的报文,对方一定接收到了。
以上的过程对客户端和服务器都是适用的,服务器给客户端发报文,客户端也需要发送应答报文。除此之外,发送应答报文的过程是双方操作系统自动完成的。
在实际情况中,发送方一次发多条报文,而不是一次只发一条报文,接收方需要对收到的所有报文做出应答,这时候就需要标识符来区分发送方发送的报文,也需要标识符来确定接收方发出去的应答报文是应答哪一条报文,于是有了序号和确认序号。
序号和确认序号(简易理解)
序号可以区分报文,应答报文的确认序号是要应答的报文的序号加一。报文的发送方在收到确认序号后,就知道确认序号之前的数据都被接收方接收了。比如 A 给 B 发报文,B 给 A 的确认序号是 1001,那么 A 就知道 B 收到了序号为 1~1000 的数据。
一个报文为什么既需要序号,又需要确认序号呢?
其实,接收方在回应发送方,告诉发送方自己接收到了报文的同时,也可以告诉发送方新的消息,就像朋友回复我 “吃了” 的时候,朋友同时也可以问我 “你吃了什么”。
当一方(例如B)接收到另一方(例如A)的数据段时,B通常需要向A发送一个应答来确认收到了哪些数据。如果此时B也有数据要发送给A,则B可以将应答信息包含在自己的数据段头部中一起发送出去。这就避免了专门为应答分配一个独立的TCP段,从而节省了带宽。因此,在一个TCP会话中,双方都可以既是发送者也是接收者。这样的应答叫做捎带应答。如果报文只有序号,或者只有确认序号,就无法知道捎带应答是应答,还是要发新数据。
超时重传
在主机 A 向 主机 B 发报文后,需要等待 主机 B 的应答,如果主机 A 没有收到应答,只能判定 主机 B 没有收到主机 A 发的报文,主机 A 重新发送该报文,那么主机 A 需要等多久,才能认为主机 B 没有收到报文呢?
所以需要设置时间,超过这个时间主机 A 还没有收到应答,就重新发送报文,这个时间就是超时重传时间。在TCP协议中,超时重传的时间(Retransmission Timeout, RTO)并不是固定的,而是根据网络状况动态调整的。如果超时时间设的太长, 会影响整体的重传效率;如果超时时间设的太短, 有可能会频繁发送重复的包。
Linux 中(BSD Unix 和 Windows 也是如此), 超时以 500ms 为一个单位进行控制, 每次判定超时重发的超时时间都是 500ms 的整数倍。
- 如果重发一次之后, 仍然得不到应答, 等待 2*500ms 后再进行重传。
- 如果仍然得不到应答, 等待 4*500ms 进行重传. 依次类推, 以指数形式递增。
- 累计到一定的重传次数, TCP 认为网络或者对端主机出现异常, 强制关闭连接
TCP报头首部的标志位
为什么需要标志位
主机 A 和 主机 B 通信的过程中,同时有很多的主机在和主机 B 通信,这些主机有的发送建立连接的报文,有的发送正常通信的报文,有的发送断开连接的报文,这些报文的类型是不一样的,所以需要标志位来区分不同类型的报文。
各个标志位的意义
TCP报文中的标志位用于控制TCP连接的状态和数据传输的过程,用来指示报文段的特定用途或要求接收方采取的行动,以下是TCP报文中的常见六个标志位:
- URG(urgent):紧急指针是否有效
- ACK(acknowledgement):确认号是否有效,当发送应答报文时,ACK置1
- PSH(push):提示接收端的应用程序立刻从 TCP 的接收缓冲区把数据读走
- RST(reset):对方要求重新建立连接
- SYN(synchronize sequence numbers):请求建立连接
- FIN(finish):发送方已经没有数据要发送了,本端要断开连接了
TCP 建立连接:三次握手
三次握手是TCP/IP协议中用于在客户端和服务器之间建立连接的过程。通过这个过程,通信双方可以同步初始序列号并确认彼此的接收能力,确保后续数据传输的准确性和可靠性。以下是三次握手的具体步骤:
第一次握手:由客户端发送一个带有SYN标志位设置为1的TCP报文给服务器,表示请求建立连接。
第二次握手:服务器接收到客户端的SYN报文后,会回复一个同样带有SYN标志位设置为1的报文,以表明同意建立连接,同时也将ACK标志位设置为1,用来对客户端的SYN进行确认。
第三次握手:客户端收到服务器的SYN+ACK报文后,需要再次发送一个报文给服务器作为响应,这次报文中的ACK标志位置为1,用来确认收到了服务器的SYN。此时,客户端与服务器之间的TCP连接成功建立,可以开始进行数据传输。
通过这三次握手,客户端和服务器都能确定对方的接收和发送能力正常,从而确保了连接的可靠性。在三次握手的过程中,双方发的都是报头,并不会发数据。
如果 第二个 ACK 报文丢包了怎么办?RST 报文
经过第一、二次握手时,主机 A 认为连接已经建立好了,并向主机 B 发送 ACK 报文, 主机 B 在收到 主机 A 发送的 ACK 报文后,才认为连接建立好了,也就是说,主机 A 和 主机 B 认为连接建立好的时间点是错开的。
如果主机 A 发送的 ACK 报文丢包了,主机 B 认为连接还没有建立好,但 主机 A 并不知道这一情况,就向 主机 B 发送数据了,这时候主机 B 就需要告诉主机 A 连接还没有建立好,所以 主机 B 向主机 A 发送 RST 报文 ,要求主机 A 关闭与主机 B 建立好的连接,重新与主机 B 进行三次握手。
通信双方是谁先发起连接的呢?
谁先调用 connect 函数,谁就先发起连接。客户端发送 SYN 置为1的报头后,只有处于 listen 状态(即,调用了listen函数)的服务器才可以受理 SYN 置为 1 的报文,并回复 ACK 置为 1 的报文,如果服务器没有处于 listen 状态,就会丢弃 SYN 置为 1 的报文。connect 函数在三次握手期间,一直阻塞等待,等待三次握手的结果,三次握手成功 connect 返回值为 0,失败则返回值为 -1.
连接的维护需要成本吗?
服务器同时与多个客户端建立连接,就需要管理这些连接,根据先描述再组织,内核中存在一个数据结构来管理连接,对连接的管理本质就是对内核数据结构的管理,这些数据结构会消耗操作系统的内存空间和时间,所以连接的维护需要时间和空间成本。
为什么是三次握手?而不是一次、两次?
1、TCP 是全双工的,需要保证通信双方既可以发消息,也可以接收消息。
主机 A 收到 主机 B 的 ACK 报文,说明主机 A 确认 主机 B 既可以接收消息(因为主机B收到了 SYN 报文才会发 ACK 报文),也可以发消息(主机 B 发了 ACK 报文),但是主机 B 还无法确认主机 A 是否可以接收消息,当主机 A 向 主机 B 发送 ACK 报文时,主机 B 确定了主机 A 可以接收消息,那么主机 A 和主机 B 都是可以接收消息和发消息的,就可以保证全双工。也就是说,三次握手是确认全双工的最小次数。一次握手和两次握手无法确认全双工,而更多的握手次数会消耗网络资源,所以三次握手是最合适的。
2、我们知道连接的维护是需要成本的,如果大量的主机向主机 B 发起连接,这些连接只是经过一次,或者两次握手,服务器无法知道哪些连接是成功的,哪些连接是失败的,但是服务器需要同时维护成功和失败的连接,那么服务器就会出现很多闲置连接(已经建立但长时间未进行数据传输或操作的连接),从而消耗服务器的资源。
3、其实三次握手,也可以看作四次握手,只是中间的两次握手,即主机 B 向主机 A 的 ACK 和 SYN 报文,被合并为捎带应答报文了。
TCP 断开连接:四次挥手
第一次挥手:主动关闭方(可以是客户端或服务器,视具体情况而定)发送一个FIN(Finish)标志位设置为1的报文段,表示希望断开连接。此时,该方进入FIN_WAIT_1状态。
第二次挥手:被动关闭方接收到FIN报文后,会回复一个ACK(Acknowledgment)报文段确认收到了对方的关闭请求,并且将序号调整为接收到的FIN报文序列号加1。之后,被动关闭方进入CLOSE_WAIT状态,而主动关闭方收到这个ACK后进入FIN_WAIT_2状态。
第三次挥手:当被动关闭方准备好关闭连接时(即它也没有数据要发送了),它会发送自己的FIN报文段给主动关闭方,表示同意关闭连接。这时,被动关闭方进入LAST_ACK状态。
第四次挥手:主动关闭方收到被动关闭方的FIN报文后,需要再次发送一个ACK报文作为回应,并将序号设置为接收到的FIN报文序列号加1。然后,主动关闭方进入TIME_WAIT状态,等待一段时间(通常是MSL,最大报文生存时间的两倍,以确保网络中的重复报文已消失)后最终关闭连接。被动关闭方在收到这个ACK后立即关闭连接。
为什么中间两次挥手不合并?
断开连接,应该看作 主机 A 与 主机 B 断开连接,主机 B 也和主机 A 断开连接。主机 A 与主机 B 断开连接时,意味着 主机 A 已经没有数据要发给主机 B 了,主机 A 要关闭发送缓冲区了,但是 主机 B 可能还要主机 A 发消息,或者有的报文还在网络中阻塞,所以需要等消息都被接收后,主机 B 才发报文,与主机 A 断开连接。所以在中间两次挥手之间,需要等待一段时间,等待消息的到达。
相关文章:

【TCP 协议】确认应答机制 超时重传 三次握手 四次挥手
TCP报文首部 确认应答机制 TCP 是可靠的,指的是它能够确保数据从源端准确无误地传输到目的端。 当客户端和服务器通信时,客户端向服务器发送报文,那么,客户端怎么知道服务器已经收到报文了呢? 服务器收到客户端发的报…...

jenkins-k8s pod方式动态生成slave节点
一. 简述: 使用 Jenkins 和 Kubernetes (k8s) 动态生成 Slave 节点是一种高效且灵活的方式来管理 CI/CD 流水线。通过这种方式,Jenkins 可以根据需要在 Kubernetes 集群中创建和销毁 Pod 来执行任务,从而充分利用集群资源并实现更好的隔离性…...

基于vue和elementui的简易课表
本文参考基于vue和elementui的课程表_vue实现类似课程表的周会议列表-CSDN博客,原程序在vue3.5.13版本下不能运行,修改两处: 1)slot-cope改为v-slot 2)return background-color:rgb(24 144 255 / 80%);color: #fff; …...

可用的IPv6公共DNS(2025年1月更新)
境内IPv6 DNS: 1. 腾讯DNS:2402:4e00:: 2. 阿里DNS:2400:3200::1、2400:3200:baba::1 3. ISP(电信服务运营商)的IPv6 DNS,请以各ISP实际下发的为准,或拨打10000、10010、10086等号码询问人工…...

c高级复习
c高级复习...

电子信息工程专业主要研究哪一方面东西?
序言: 如今科技发展那叫一个迅猛,电子信息专业可是站在这股浪潮的 C 位,狠狠推动着社会向前跑。这专业就像一座神奇桥梁,把虚拟数字和现实生活紧紧相连,把那些信号变成咱们看到的画面、听到的声音。你看,从…...

RU 19.26安装(手工安装各个补丁)
使用手工方式打RU19.26 参考文档: Supplemental Readme - Grid Infrastructure Release Update 12.2.0.1.x / 18c /19c (Doc ID 2246888.1) 操作步骤: 1 Stop the CRS managed resources running from DB homes. 2 Run the pre root script. 3 Patch GI…...

深入理解Pytest中的Setup和Teardown
关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 对于简单程序而言,使用 Pytest 运行测试直截了当。然而,当你…...

如何利用AI工具来进行数据分析
利用AI工具进行数据分析可以显著提高效率和准确性,以下是详细步骤和方法: 1. 明确分析目标 在开始数据分析之前,首先需要明确分析的目标和问题。这包括确定需要解决的问题、期望的见解或结果,以及选择合适的AI工具和方法。 2. …...

具身智能体俯视全局的导航策略!TopV-Nav: 解锁多模态语言模型在零样本目标导航中的顶视空间推理潜力
作者:Linqing Zhong, Chen Gao, Zihan Ding, Yue Liao, Si Liu 单位:北京航空航天大学,新加坡国立大学,香港中文大学多模态实验室 论文标题:TopV-Nav: Unlocking the Top-View Spatial Reasoning Potential of MLLM …...

npm:升级自身时报错:EBADENGINE
具体报错信息如下: 1.原因分析 npm和当前的node版本不兼容。 // 当前实际版本: Actual: {"npm":"10.2.4","node":"v20.11.0"}可以通过官网文档查看与自己 node 版本 兼容的是哪一版本的npm,相对应进行更新即可…...

微信小程序实现自定义日历功能
文章目录 1. 创建日历组件实现步骤:2. 代码实现过程3. 实现效果图4. 关于作者其它项目视频教程介绍 1. 创建日历组件实现步骤: 创建日历组件:首先,你需要创建一个日历组件,包含显示日期的逻辑。样式设计:为…...

Vue 3 中的 toRef 与 toRefs:使用与案例解析
在 Vue 3 的响应式系统中,toRef 和 toRefs 是两个非常实用的工具函数。它们主要用于将响应式对象的属性转换为单独的 ref,以便在模板或逻辑中更方便地使用。本文将详细介绍 toRef 和 toRefs 的用法,并通过一个老师信息的案例来演示它们的实际…...

问题修复记录:Linux docker 部署 dify,无法调用宿主机本地服务
重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…...

代码随想录day20
235. 利用二叉搜索树的特性即可 /** lc appleetcode.cn id235 langcpp** [235] 二叉搜索树的最近公共祖先*/// lc codestart /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) :…...

【ProxyBroker】用Python打破网络限制的利器
ProxyBroker 1. 什么是ProxyBroker2. ProxyBroker的功能3. ProxyBroker的优势4. ProxyBroker的使用方法5. ProxyBroker的应用场景6.结语项目地址: 1. 什么是ProxyBroker ProxyBroker是一个开源工具,它可以异步地从多个来源找到公共代理,并同…...

分布式微服务系统架构第88集:kafka集群
使用集 群最大的好处是可以跨服务器进行负载均衡,再则就是可以使用复制功能来避免因单点故 障造成的数据丢失。在维护 Kafka 或底层系统时,使用集群可以确保为客户端提供高可用 性。 需要多少个broker 一个 Kafka 集群需要多少个 broker 取决于以下几个因…...

RocketMQ原理—5.高可用+高并发+高性能架构
大纲 1.RocketMQ的整体架构与运行流程 2.基于NameServer管理Broker集群的架构 3.Broker集群的主从复制架构 4.基于Topic和Queue实现的数据分片架构 5.Broker基于Pull模式的主从复制原理 6.Broker层面到底如何做到数据0丢失 7.数据0丢失与写入高并发的取舍 8.RocketMQ读…...

下载Visual Studio Community 2019
官方链接如下:Visual Studio Community 2019下载链接 https://learn.microsoft.com/zh-cn/visualstudio/releases/2019/system-requirements#download 目前官方仅建议2022版,已经关闭vs2019等旧版本,哪天开放了,记得踢我一下。 …...

一文简单回顾Java中的String、StringBuilder、StringBuffer
简单说下String、StringBuilder、StringBuffer的区别 String、StringBuffer、StringBuilder在Java中都是用于处理字符串的,它们之间的区别是String是不可变的,平常开发用的最多,当遇到大量字符串连接的时候,就用StringBuilder&am…...

27. C语言 强制类型转换详解
本章目录: 前言强制类型转换(Type Casting)强制类型转换的语法示例1:将整数转换为浮点数输出结果: 代码解析: 整数提升(Integer Promotion)示例2:整数提升输出结果: 代码…...

git困扰的问题
.gitignore中添加的某个忽略文件并不生效 把某些目录或文件加入忽略规则,按照上述方法定义后发现并未生效, gitignore只能忽略那些原来没有被追踪的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。 解决方…...

反向代理模块。。
1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说,反向代理就相当于…...

【Linux基础指令】第三期
近期更新的基础指令链接: 【Linux基础指令】第一期-CSDN博客 【Linux基础指令】第二期-CSDN博客 本期博客的主题依旧是 "基础指令" ;话不多说,正文开始。 一、Linux的指令 1.zip / unzip 功能:打包压缩 命令格式&…...

Jenkins安装部署(以及常见报错解决方案),jdk版本控制器sdkman
目录 零、环境介绍 一、Jenkins安装 1、插件安装以及更换插件源 2、修改jenkins时区 二、sdkman安装(可选) 1、sdkman常用方法 2、sdkman常用方法演示 2.1、查看可用的jdk 2.2、下载jdk并切换版本 三、jenkins报错解决 1、下载sdkman后systemc…...

利用JSON数据类型优化关系型数据库设计
利用JSON数据类型优化关系型数据库设计 前言 在关系型数据库中,传统的结构化存储方式要求预先定义好所有的列及其数据类型。 然而,随着业务的发展,这种设计可能会显得不够灵活,尤其是在需要扩展单个列的描述功能时。 JSON数据…...

Nxopen 直齿轮参数化设计
NXUG1953 Visualstudio 2019 参考论文: A Method for Determining the AGMA Tooth Form Factor from Equations for the Generated Tooth Root Fillet //FullGear// Mandatory UF Includes #include <uf.h> #include <uf_object_types.h>// Internal I…...

线程配置经验
工作时,时常会遇到,线程相关的问题与解法,本人会持续对开发过程中遇到的关于线程相关的问题及解决记录更新记录在此篇博客中。 目录 一、线程基本知识 1. 线程和进程 二、问题与解法 1. 避免乘法级别数量线程并行 1)使用线程池…...

火语言RPA--KimiAiFree服务
🚩【组件功能】:KimiAiFree服务支持联网搜索、支持智能体对话、支持长文档解读、支持图像OCR。 配置预览 配置说明 服务地址 支持T或# 自行搭建或第三方提供的KimiAiFree服务地址。 RefreshToken 支持T或# 与KimiAiFree服务交互时用到的token。从ki…...

P6120 [USACO17JAN] Hoof, Paper, Scissor S
难度:普及/提高−; 题意: 石头、剪刀、布游戏,先给出 n n n 轮已经知道的其中一人的对局情况,例如样例: 5 P - 布 P - 布 H - 石头 P - 布 S - 剪刀另外一人,只允许修改一次机会的情况下…...