传输层协议TCP ( 下 )
文章目录
- 前言
- 序号与确认序号
- 超时重传
- RTO
- Jacobson算法
- 内核中超时时间的计算
- 滑动窗口
- 滑动窗口
- 延迟应答
- 流量控制
- 拥塞控制
- 慢启动
- 拥塞避免
- 快重传
- 快速恢复
- 保活机制
- 参考资料
前言
TCP(Transmission Control Protocol,传输控制协议)是互联网最重要的协议之一,为应用层提供可靠的、面向连接的数据传输服务。它广泛应用于 HTTP、FTP、SMTP 等协议中,保障数据能够准确、有序地到达目标设备。本文将主要介绍TCP其他保证可靠性机制
序号与确认序号
TCP是面向字节流的协议,数据在传输时并不以数据包为单位,而是以字节为单位进行传输。每个 TCP 数据段都会携带一个序号,指示数据段中第一个字节的位置, 如果将字节流看作在两个应用程序间的单向流动,则可以看作 TCP 用序号对每个字节进行计数。序号是32 bit的无符号数,序号到达 23^2-1后又从0开始, 由于IP协议是不可靠无序的, 不同的 IP 报文可能通过不同的路由到达目标主机的顺序不同, TCP 要保证可靠性, 就需要对这些乱序的报文进行排序, TCP 报文中的 32位序号就是用于报文排序
首部 32位确认序号用于确保数据传输的可靠性和顺序性。它是接收端告诉发送端,在这个确认序号之前的报文都收到了,
例如:如果发送方发送了1000 - 1099 和1100 - 1199的数据, 如果接收端已经成功接收到这两个报文的数据,那么它的确认序号将是 1200,表示1200以前的报文都收到了, 如果发送丢包, 比如接收方只接收到了 1000 - 1099 的数据, ,那么它的确认序号将是 1100, 如果是前一个报文1000 - 1099 丢失后一个报文收到, 根据确认序号的意义, 此时确认序号不可能是1100和1200, 确认序号将是1000
超时重传
TCP 提供可靠的运输层。它使用的方法之一就是确认从另一端收到的数据。但数据和确认都有可能会丢失。TCP 通过在发送时设置一个定时器来解决这种问题。如果当定时器到期时还没有收到确认,它就重传该数据
RTO
超时重传机制中的关键是 重传超时时间(Retransmission Timeout,RTO),即发送方等待接收方确认的最大时间。RTO的选择是动态的,不是一个固定值,而是根据网络的当前状况来调整
- 《TCP-IP详解卷1:协议》中表示可以通过一下公式估计
RTO = A + 4D
- RFC-793 3.7 给出的计算方法为
SRTT = (ALPHA * SRTT) + ((1 - ALPHA) * RTT)
RTO = min[UBOUND, max[LBOUND, (BETA * SRTT)]]
- 其中,UBOUND是超时的上限(例如1分钟),LBOUND是超时的下限(例如1秒),ALPHA是平滑因子(例如0.8到0.9),BETA是延迟方差因子(例如1.3到2.0)。
- RFC-1122 4.2.3.1 指出RFC-793中建议的计算重传超时的算法现在被认为是不充分的, 并重新给出计算
主机TCP必须实现Karn算法和Jacobson算法来计算重传超时(“RTO”)。
- Jacobson算法用于计算平滑的往返时间(“RTT”),它包括一个简单的方差度量[TCP:7]。
- Karn算法用于选择RTT测量,确保不明确的往返时间不会破坏平滑往返时间的计算[TCP:6]。
该实现还必须包括“指数回退”机制,用于相同段的连续RTO值计算。SYN段的重传应使用与数据段相同的算法。
Jacobson算法
SRTT = aRTT + (1-a)SRTT
RTTVAR = (1-b)RTTVAR + b|SRTT-RTT|
RTO=SRTT+max(G,4×RTTVAR)
- a 是平滑因子,通常设定为7/8
- b 是另一种平滑因子,通常设置为 0.25
RFC-1122 4.2.3.1 指出:
以下值应当用于初始化新连接的估算参数
(a) RTT = 0秒。
(b) RTO = 3秒。(平滑方差应初始化为能够产生此RTO的值)。
RTO的推荐上下限已知在大规模互联网中不足以满足要求。下限应以秒的分数来衡量(以适应高速局域网),上限应为2*MSL,即240秒。
内核中超时时间的计算
参考Linux2.6内核源码中, 发现RTO初始化使用了RFC 1122
#define HZ 100
#define TCP_TIMEOUT_INIT ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value */
在static int tcp_v4_init_sock(struct sock *sk)中初始化时就会使用TCP_TIMEOUT_INIT初始化一个连接的RTO
static int tcp_v4_init_sock(struct sock *sk)
{struct tcp_sock *tp = tcp_sk(sk);skb_queue_head_init(&tp->out_of_order_queue);tcp_init_xmit_timers(sk);tcp_prequeue_init(tp);tp->rto = TCP_TIMEOUT_INIT;//初始化RTOtp->mdev = TCP_TIMEOUT_INIT;......
}
在超时重传时, tatic void tcp_retransmit_timer(struct sock *sk)对RTO做处理
static void tcp_retransmit_timer(struct sock *sk)
{....../*** 如果重传超时,检查当前资源使用情况并决定是否重传。* 如果重传次数达到上限,则需要强制关闭套接字。* 如果仅资源使用达到上限,则不重传。*/if (tcp_write_timeout(sk))goto out;......out_reset_timer:/* 设置重传超时时间,然后重置重传定时器 */tp->rto = min(tp->rto << 1, TCP_RTO_MAX);//2倍扩tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto);if (tp->retransmits > sysctl_tcp_retries1)__sk_dst_reset(sk);......
}
#define TCP_RTO_MAX ((unsigned)(120*HZ))
可以看出RTO初始值为3秒, 最大值为120秒, 每次超时重传2倍增加, 不超过120秒, 并且如果重传次数达到上限就会关闭该连接
滑动窗口
滑动窗口
对每一个发送的数据段, 都要给一个ACK确认应答, 收到ACK后再发送下一个数据段.这样做有一个比较大的缺点, 就是性能较差, 尤其是数据往返的时间较长的时候, 那么我们一次发送多条数据, 以此提高性能
滑动窗口(是缓冲区的一部分,size=min(对方接收缓冲区剩余空间的大小, 拥塞窗口大小)
- 窗口大小指的是无需等待确认应答而可以继续发送数据的最大值, 比如一个滑动窗口有四个段
- 发送前四个段的时候, 不需要等待任何 ACK, 直接发送
- 收到第一个 ACK 后, 滑动窗口向后移动, 继续发送第五个段的数据, 依次类推
- 操作系统内核为了维护这个滑动窗口, 需要开辟发送缓冲区来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉
延迟应答
如果接收数据的主机的接收缓冲区很小, 此时如果立刻返回ACK应答, 这时候返回的窗口也比较小, 这样发送方在后续的传输中就可能会受到限制,因为它只能发送少量的数据, 为了提高传输效率, 接收方可以延迟一段时间再发送ACK, 等待一段时间让上层将接收缓冲区的数据读取, 那么自身的接收能力就提高了, 返回的窗口大小更大, 发送方就可以一次发送更多的数据, 当然也不是所有包都能延迟应答, 一些实时性较高的场景会导致应用层性能下降
流量控制
接收端处理数据的速度是有限的, 如果发送方太快以至于接收方来不及处理的, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包, 继而引起丢包重传等等一系列连锁反应, 因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度, 这个机制就叫做流量控制(Flow Control)
- 接收端将自己可以接收的缓冲区大小放入TCP首部中的 16位窗口大小字段和附加首部选项 ( 16位可能不够 ) 通知对方自己的接收能力
- 如果接收端缓冲区满了,就会将窗口置为0, 这时发送方不再发送数据,但是会定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端
拥塞控制
TCP 协议中用于防止网络出现过度拥塞的机制。它的目标是确保网络在高负载下依然能够有效传输数据,避免由于拥塞引起的丢包和延迟问题, 因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵, 在不清楚当前网络状态下, 贸然发送大量的数据可能会加重网络拥堵程度, 首先是慢启动拥塞窗口指数增长, 拥塞窗口达到阈值后成线性增长, 直到发生大量丢包, 认为网络堵塞, 拥塞窗口阈值将置为当前拥塞窗口大小一半, 然后将拥塞窗口设置1, 重新慢启动
慢启动
慢启动为发送方的 TCP 增加了另一个窗口:拥塞窗口(congestion window),记为 cwnd
-
初始时,TCP 的 拥塞窗口 被设置为一个较小的值,通常为 1 或 2 个最大报文段(MSS,Maximum Segment Size)。
-
每收到一个 确认(ACK),拥塞窗口会 增加 1 个 MSS。
-
在慢启动阶段,拥塞窗口每经过一个往返时间(RTT),就会指数增长。这种指数增长非常快速,直到达到网络的承载能力或进入下一个阶段。
-
当TCP开始启动的时候,慢启动阈值等于窗口最大值
-
当拥塞窗口达到阈值时,进入 拥塞避免阶段
拥塞避免
当慢启动的拥塞窗口超过慢启动阈值的时候,不再按照指数方式增长,而是按照线性方式增长
- 在拥塞避免阶段,拥塞窗口每经过一个 RTT 就增加一个 MSS(线性增长),而不是像慢启动阶段那样指数增长。
- 线性增长的目的是平稳地增加数据传输速率,避免网络中出现拥塞
- 当网络状态稳定且没有发生拥塞时,TCP 会逐步增加发送窗口,充分利用带宽
- 当拥塞发生时(超时或收到重复确认),拥塞窗口阈值被设置为当前窗口大小的一半(拥塞窗口和接收方通告窗口大小的最小值,但最少为 2个报文段)。此外,如果是超时引起了拥塞,则拥塞窗口被设置为1个报文段(重新开始慢启动)。
快重传
当发送方接收到 三个重复的 ACK,它推测网络中丢失了某些数据包。发送方会立即进行重传,这时会进入快速恢复阶段
结合之前的确认序号, 比如发送方发送了序号1000 - 1099 1100 - 1199 1200 - 1299 1300 - 1399 这四个报文, 如果第一个报文丢失, 因为确认序号表示该序号的以前的报文都收到了, 第一个报文没有收到, 即时后面的报文都收到了, 接收方对于后面几个报文的应答中确认序号依然是1000, 此时发送方收到三个确认序号相同的ACK, 发送方就知道是1000这个报文丢失了, 此时发送方会立即进行重传
快速恢复
快速恢复是在发生丢包情况下, 用来快速恢复数据的发送速率,并避免过度减小拥塞窗口, 通常和快重传搭配,
- 将 拥塞窗口设置为当前的慢启动阈值,即 cwnd = ssthresh。
- 将 慢启动阈值(ssthresh)设置为当前的 cwnd / 2,目的是减少发送速率,避免过多的数据继续传输到网络中。
- 发送方继续发送数据,但 cwnd 不会像慢启动那样从 1 MSS 开始增大,而是通过线性增长恢复发送速率。
保活机制
TCP 保活机制是确保 TCP 连接在长时间空闲的情况下不会因为网络故障或对方设备问题而中断的机制。它通过周期性地发送小的数据包来检查连接的状态,确保通信双方都处于活动状态。
通过一个半开放连接发送数据会导致返回一个复位, 但那是在来自正在发送数据的客户端。如果客户已经消失了,使得在服务器上留下一个半开放连接,而服务器又在等待来自客户的数据,则服务器将永远等待下去。保活功能就是试图在服务器端检测到这种半开放的连接
- 检测死连接:TCP 保活机制主要用于检测长时间没有数据传输的连接是否仍然处于活动状态。如果对方没有响应,发送方可以确定连接已经断开或发生了网络问题。
- 避免空闲连接超时:一些防火墙和路由器可能会在连接空闲时间较长时自动断开连接。TCP 保活机制可以防止这些设备因空闲超时而丢弃连接
TCP 保活机制通过周期性地发送保活探测包来检查连接是否仍然有效
- 空闲连接:在 TCP 连接长时间没有数据传输时,发送方开始启动保活机制。这个空闲时间通常由 TCP 保活探测间隔(TCP_KEEPIDLE) 配置。
- 发送保活探测包:如果没有接收到数据包,TCP 会按照一定的间隔周期发送小的 保活探测包(通常是 1 字节的数据包),并等待接收方的响应。
- 等待接收方响应:如果接收方仍然存在并且连接正常,它会返回一个 ACK 来确认收到保活探测包, 如果发送方连续发送了多个保活探测包都没能得到响应, 那么发送方会认为该连接已经关闭, 从而关闭连接
参考资料
- 《TCP/IP详解 卷1: 协议》
- Linux2.6内核源码
- RFC - 793(RFC 793: Transmission Control Protocol)
- RFC - 1122(RFC 1122: Requirements for Internet Hosts - Communication Layers)
相关文章:

传输层协议TCP ( 下 )
文章目录 前言序号与确认序号超时重传RTOJacobson算法内核中超时时间的计算 滑动窗口滑动窗口延迟应答流量控制 拥塞控制慢启动拥塞避免快重传快速恢复 保活机制参考资料 前言 TCP(Transmission Control Protocol,传输控制协议)是互联网最重要…...

NLP 八股 DAY1:BERT
BERT全称:Pre-training of deep bidirectional transformers for language understanding,即深度双向Transformer。 模型训练时的两个任务是预测句⼦中被掩盖的词以及判断输⼊的两个句⼦是不是上下句。在预训练 好的BERT模型后⾯根据特定任务加上相应的⽹…...

演示synchronized锁机制用法的简单Demo
演示synchronized锁机制用法的简单Demo。我们以"银行开户"场景为例:每个用户只能创建一个账户(模拟类似原代码中每个用户只能有一个私有空间的限制)。 第1步:创建项目结构 demo-lock ├── src/main/java/com/exampl…...

Datawhale 数学建模导论二 笔记1
第6章 数据处理与拟合模型 本章主要涉及到的知识点有: 数据与大数据Python数据预处理常见的统计分析模型随机过程与随机模拟数据可视化 本章内容涉及到基础的概率论与数理统计理论,如果对这部分内容不熟悉,可以参考相关概率论与数理统计的…...
差分解方程
差分解方程 差分法在数值求解偏微分方程(PDEs)和常微分方程(ODEs)时,可以分为隐式格式和显式格式。以下是两者的主要区别: 显式格式(Explicit Scheme) 时间推进: 显式格…...

EasyExcel 复杂填充
EasyExcel Excel表格中用{}或者{.} 来表示包裹要填充的变量,如果单元格文本中本来就有{、}左右大括号,需要在括号前面使用斜杠转义\{ 、\}。 代码中被填充数据的实体对象的成员变量名或被填充map集合的key需要和Excel中被{}包裹的变量名称一致。 …...
ESP32通过MQTT连接阿里云平台实现消息发布与订阅
文章目录 前言 一、准备工作 二、阿里云平台配置 三、代码实现 总结 前言 本文将介绍如何使用ESP32开发板通过MQTT协议连接阿里云物联网平台,并实现消息的发布与订阅功能。我们将使用Arduino IDE进行开发,并借助PubSubClient库实现MQTT通信。 一、准备…...

NVIDIA Jetson Orin Nano 刷机过程
1. 背景 新到手 NVIDIA Jetson Orin Nano 插上显示屏,显示如下: 这是UEFI Shell,UEFI Shell(统一可扩展固件接口外壳程序)是一种基于UEFI规范的交互式命令行工具,它运行在UEFI固件环境中,为用…...
C#学习之数据转换
目录 一、创作说明 二、数据类型之间的转换 1.数据类型之间的转换表格 2.代码示例 三、进制之间的转换 1.进制之间的转换表格 2.代码示例 四、ASCII 编码和字符之间的转换 1.ASCII 编码和字符之间的转换表格 2.代码示例 五、总结 一、创作说明 C#大多数时候都是和各…...

typecho快速发布文章
typecho_Pytools typecho_Pytools工具由python编写,可以快速批量的在本地发布文章,不需要登陆后台粘贴md文件内容,同时此工具还能查看最新的评论消息。… 开源地址: GitHub Gitee 使用教学:B站 一、主要功能 所有操作不用登陆博…...

深度学习R4周:LSTM-火灾温度预测
🍨 本文为🔗365天深度学习训练营中的学习记录博客🍖 原作者:K同学啊 任务: 数据集中提供了火灾温度(Tem1)、一氧化碳浓度(CO 1)烟雾浓度(Soot 1)…...
探索Java中的集合类_特性与使用场景
1. 引言 1.1 Java集合框架概述 Java集合框架(Java Collections Framework, JCF)是Java中用于存储和操作一组对象的类和接口的统称。它提供了多种数据结构来满足不同的需求,如列表、集合、映射等。JCF的核心接口包括Collection、List、Set、Queue和Map,以及它们的各种实现…...

自动化遇到的问题记录(遇到问题就更)
总结回归下自己这边遇到的一些问题 “EOF错误”,获取不到csv里面的内容 跑多csv文件里的场景,部分场景的请求值为 1、检查csv文件里不能直接是[]开头的参数,把[]改到ms平台的请求参数里 2、有时可能是某个参数值缺了双引号的其中一边 met…...

【云安全】云原生- K8S kubeconfig 文件泄露
什么是 kubeconfig 文件? kubeconfig 文件是 Kubernetes 的配置文件,用于存储集群的访问凭证、API Server 的地址和认证信息,允许用户和 kubectl 等工具与 Kubernetes 集群进行交互。它通常包含多个集群的配置,支持通过上下文&am…...
【愚公系列】《Python网络爬虫从入门到精通》008-正则表达式基础
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...

【Linux】Ext2文件系统、软硬链接
Ext2文件系统 一.理解硬件1.磁盘、服务器、机柜、机房2.磁盘的物理结构3.磁盘的存储结构4.磁盘的逻辑结构1.理解过程2.真实过程 5.CHS地址、LBA地址转换 二.引入文件系统1.引入"块"概念2.引入"分区"概念3.引入"inode"概念 三.Ext2文件系统1.宏观…...

ATF系统安全从入门到精通
CSDN学院课程连接:https://edu.csdn.net/course/detail/39573...

【算法专场】哈希表
目录 前言 哈希表 1. 两数之和 - 力扣(LeetCode) 算法分析 算法代码 面试题 01.02. 判定是否互为字符重排 编辑算法分析 算法代码 217. 存在重复元素 算法分析 算法代码 219. 存在重复元素 II 算法分析 算法代码 解法二 算法代码 算法…...

Beszel监控Docker安装
一、Beszel Hub安装 #Beszel Hub安装 mkdir -p ./beszel_data && \ docker run -d \--name beszel \--restartunless-stopped \-v ./beszel_data:/beszel_data \-p 8090:8090 \henrygd/beszel#创建账号 账号/密码:adminadmin.com/adminadmin.com 二、Besz…...
如何学习Elasticsearch(ES):从入门到精通的完整指南
如何学习Elasticsearch(ES):从入门到精通的完整指南 嘿,小伙伴们!如果你对大数据搜索和分析感兴趣,并且想要掌握Elasticsearch这一强大的分布式搜索引擎,那么你来对地方了!本文将为…...
反向工程与模型迁移:打造未来商品详情API的可持续创新体系
在电商行业蓬勃发展的当下,商品详情API作为连接电商平台与开发者、商家及用户的关键纽带,其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息(如名称、价格、库存等)的获取与展示,已难以满足市场对个性化、智能…...

【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
libfmt: 现代C++的格式化工具库介绍与酷炫功能
libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库,提供了高效、安全的文本格式化功能,是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全:…...

ubuntu22.04有线网络无法连接,图标也没了
今天突然无法有线网络无法连接任何设备,并且图标都没了 错误案例 往上一顿搜索,试了很多博客都不行,比如 Ubuntu22.04右上角网络图标消失 最后解决的办法 下载网卡驱动,重新安装 操作步骤 查看自己网卡的型号 lspci | gre…...