面向连接的运输:TCP

目录

TCP连接

TCP报文段结构

往返时间估计与超时

可靠数据传输 

回退N步or超时重传

超时间隔加倍

快速重传

流量控制

TCP连接管理 

三次握手

1. 客户端 → 服务器:SYN 包

2. 服务器 → 客户端:SYN+ACK 包

3. 客户端 → 服务器:ACK 包

四次挥手

1. 主动关闭方 → 被动关闭方:FIN 包

2. 被动关闭方 → 主动关闭方:ACK 包

3. 被动关闭方 → 主动关闭方:FIN 包

4. 主动关闭方 → 被动关闭方:ACK 包

 为什么必须要三次握手?

为什么不能用两次握手?

四次或更多次握手可行吗?

为什么要四次挥手?

为什么不能用三次挥手?

两次挥手可行吗?


TCP是因特网运输层面向连接的可靠传输协议。为了提供可靠数据传输,TCP依赖前文可靠数据传输原理 许多基本原理,其中包括差错检测,重传,累积确认,定时器以及用于序号和确认号的首部字段等。

TCP连接

TCP 被称为面向连接的协议,核心在于其通信过程需要经历 “连接建立→数据传输→连接释放” 的完整生命周期。TCP 通信前必须通过三次报文交互,在客户端和服务器之间协商并确认连接参数,确保双方具备通信能力(三次握手)。通信结束后,需通过四次报文交互主动释放连接资源,确保双方无数据残留(四次挥手)。TCP 的 “面向连接” 本质是状态化通信,连接是一种状态实体,通信依赖连接状态的一致性,错误的处理基于连接的上下文。

TCP连接提供的是全双工服务,在一个 TCP 连接中,通信双方(客户端和服务器)可以同时进行数据的发送和接收,发送方和接收方的角色是动态的、非独占的。TCP 连接包含两条独立的逻辑通道,两条通道的数据流互不干扰,各自维护独立的序列号、确认号、滑动窗口等状态信息。

TCP被设计为点对点(Point-to-Point)协议,而非一对多(如组播或广播),这是由其协议特性、设计目标和底层网络架构共同决定的。TCP 的核心定位是在两个端点之间建立一条逻辑连接,通过序列号、确认机制、滑动窗口等复杂机制实现端到端的可靠数据传输。这些机制依赖于唯一的双向通信链路,要求发送方和接收方之间有明确的一一对应关系。若支持一对多(如同时向多个接收方发送数据),每个接收方的网络状态、接收能力、数据确认逻辑均不同,需为每个接收方单独维护一套状态(如序号、窗口、超时定时器等),这会导致协议复杂度呈指数级上升,甚至无法高效管理。

TCP 将数据视为无边界的字节流,保证数据按发送顺序到达接收方。在点对点场景中,通过单一序列号空间即可实现顺序控制;但在一对多场景中,每个接收方的字节流顺序独立,发送方需为每个接收方维护独立的序列号和确认逻辑,这与 TCP 的字节流抽象模型冲突。且一对多属于网络层或应用层的职责,而TCP 专注于传输层的端到端可靠性。

应用进程将数据写入套接字后,会先存于 TCP 发送缓存,等待合适时机发送(数据暂存)。发送缓存配合滑动窗口机制,根据接收方通告的窗口大小,控制发送数据量。若接收方接收缓存快满,通告小窗口值,发送方就减少从发送缓存提取数据发送的量,避免数据丢失(流量控制)。发送缓存中未被确认的数据,在超时未收到确认时会重传(可靠传输保证)。 

TCP 报文段(TCP Segment)是 TCP在网络中传输数据的基本单位,它由首部数据部分 组成,承载着从发送端到接收端的数据以及用于实现可靠传输的控制信息。

TCP接收方将网络中传来的 TCP 报文段,经解析后数据存于接收缓存,供应用进程读取(数据接收缓存)。当收到乱序的报文段,只要序号在接收窗口内,就暂存于接收缓存,等待正确顺序时交付应用进程(乱序处理)。接收缓存剩余空间大小,决定接收方通告给发送方的窗口大小,以此反馈控制发送方发送速率(流量反馈依据)。

TCP可从缓存中取出并且放入报文段的数据数量受限于最大报文段长度(MSS)。MSS 指的是 TCP 报文段中所能承载的应用层数据的最大字节数,不包括 TCP 首部(通常 20 字节 )和 IP 首部(通常 20 字节 )。MSS通常根据最初确定的由本地发送主机发送的最大链路层帧长度,即所谓的最大传输单元(MTU)来设置。

MTU 指的是在数据链路层中,一个数据帧所能够携带的最大有效载荷(不包含帧头、帧尾等链路层控制信息)的字节数。不同的数据链路层协议,MTU 的默认值有所不同 。比如,以太网的 MTU 默认值是 1500 字节,PPP 协议的 MTU 默认值通常为 1500 字节或 296 字节,FDDI(光纤分布式数据接口)的 MTU 则为 4352 字节。

比如,若 MSS 值为 1460 字节,那么加上 20 字节的 TCP 首部和 20 字节的 IP 首部后,整个 IP 数据报长度就是 1500 字节,这恰好是以太网默认的最大传输单元(MTU)。

TCP报文段结构

TCP 报文段首部长度通常为 20 字节(不含TCP可选字段),最多可达 60 字节,包含了实现可靠传输、连接管理等功能的关键控制信息,具体如下:

  1. 源端口号和目的端口号:各占 16 比特,标识发送方和接收方应用进程所使用的端口,帮助数据准确交付给对应的应用程序。
  2. 序号:占 32 比特,标记本报文段在发送方数据字节流中的位置,用于接收方对数据进行排序。
  3. 确认号:占 32 比特,是接收方期望接收的下一个字节的序号,用于向发送方确认已收到的数据。
  4. 首部长度:占 4 比特,指示 TCP 首部的长度,以 4 字节为单位,用于明确首部结束和数据开始的位置。
  5. 标志位:占 6 比特,包含多个标志:
    • URG:紧急标志,URG = 1 时表示报文中有紧急数据。
    • ACK:确认标志,ACK = 1 时确认号字段才有效。
    • PSH:推送标志,指示接收方尽快将数据交付给上层应用。
    • RST:重置标志,用于异常时重置连接。
    • SYN:同步标志,在连接建立时同步序号。
    • FIN:结束标志,在连接释放时通知对方本方无数据发送。
  6. 窗口大小:占 16 比特,接收方通过该字段告知发送方自己当前接收缓冲区的剩余空间大小,实现流量控制。
  7. 校验和:占 16 比特,用于检测 TCP 报文段在传输过程中是否出错,计算范围包括首部、数据部分以及一个伪首部。
  8. 紧急指针:占 16 比特,当 URG 标志位为 1 时有效,指出本报文段中紧急数据的最后一个字节的序号。
  9. 选项:长度可变,最多 40 字节,用于协商额外参数,如最大段大小(MSS)、窗口扩大因子、时间戳等 。
  10. 数据部分:承载的是应用层实际要传输的数据,长度可变,受最大段大小(MSS)限制。在连接建立阶段,客户端和服务器会协商 MSS 值,以确保加上 IP 首部后的整个报文长度不超过链路层的最大传输单元(MTU),避免 IP 分片。

在 TCP 报文段结构中,序号和确认号是实现可靠传输最核心的两个字段。

TCP把数据看成无结构的,有序的字节流。序号是建立在传送的字节流之上,而不是建立在传送的报文段序列之上。因此一个报文段的序号就是该报文段首字节的字节流编号。

序号标识本报文段所携带数据在发送方字节流中的起始位置,用于解决数据分片后的排序问题。例如,若发送方发送的第一个报文段携带 1000 字节数据,序号为500,则下一个报文段的序号为1500。接收方通过序号判断数据是否按序到达,对乱序数据进行缓存或重传请求。在连接建立(三次握手)时,序号用于同步初始序列号(ISN),避免历史数据干扰新连接。

接收方通过确认号告知发送方期望接收的下一个字节的序号,表示 “该序号之前的数据已全部正确接收”。例如,接收方收到序号1-1000的数据后,会返回确认号1001,表示希望接收1001及之后的数据。发送方根据确认号判断哪些数据已被成功接收,哪些需要重传(基于超时重传机制)。同时实现可靠传输的双向确认:不仅发送方需要确认接收方收到数据,接收方也通过确认号主动告知发送方状态。

TCP 通过 “序号 + 确认号” 机制实现数据的有序性、完整性和去重性,是可靠传输的基础,其他字段均围绕二者提供辅助或扩展功能。

往返时间估计与超时

显然,由于路由器的拥塞和端系统负载的变化,TCP报文段中的rtt值也会随之波动,所以任何给定的RTT值也许不是典型的,所以这也造就了一个明显的问题:设置超时间隔的长度。因此为了估计一个典型的RTT,自然要对RTT进行一个均值操作。

TCP 采用一种基于采样的方法来估计 RTT。最初,TCP 会对每个发送的报文段进行计时,当收到对应的 ACK 时,计算实际的往返时间。然后通过加权平均的方式更新对 RTT 的估计值,一旦获得一个新的RTT,TCP就会用以下公式更新均值:

其中α是一个加权因子(通常取值在 0.125 左右 ),SampleRTT是当前测量得到的样本往返时间。

除了估算RTT以外,测量RTT的变化也是很有必要的。DEVrtt用于衡量往返时间估计值的波动情况,是计算超时时间的重要参数之一。

其中,β也是一个加权因子,一般取值为 0.25。该公式的作用是计算往返时间估计值的偏差。|SampleRTT - EstimatedRTT| 表示样本往返时间与估计往返时间的差值的绝对值,通过加权平均的方式更新 DEVrtt ,从而反映出样本往返时间围绕估计往返时间的波动程度。 

既然已经给出了EstimateRTT和DevRTT的值,TCP 的超时间隔(Timeout Interval,简称 RTO)通常使用 :

其中:δ 是一个经验系数, 该系数用于放大 EstimatedRTT 的权重,确保超时间隔足够覆盖网络波动。 4 是 δ 的典型取值,通过将偏差放大 4 倍,使 RTO 对网络延迟的波动更敏感。

可靠数据传输 

在 TCP 协议中,定时器的设置是保障可靠传输的关键机制之一。TCP 使用多种定时器来处理不同场景,其中最核心的是超时重传定时器。

TCP采用的是单计时器模型,发送方每次发送 新数据 时,若当前没有活跃的定时器,则启动一个覆盖 最早未确认数据 的定时器。当收到 最早未确认数据的 ACK 时,停止定时器。

第二个主要事件是超时处理,TCP通过超时重传来响应超时事件,然后重启定时器。 

回退N步or超时重传

TCP 的可靠性机制部分借鉴了 GBN 和 SR 的思想,根据自身需求进行了优化和融合。 

TCP使用滑动窗口机制,但 默认采用累积确认(与 GBN 类似),TCP 的滑动窗口大小可变(动态调整),而 GBN 窗口大小固定。TCP同样为未确认的数据设置定时器,超时后重传 最早未确认的分组及之后的数据(类似 GBN 的回退重传)。但是TCP 引入 快速重传机制,减少不必要的超时等待。

TCP引入 选择性确认(SACK)选项(类似SR),作为累积确认的补充。当接收方收到失序分组时,可通过 SACK 告知发送方具体哪些分段已接收,发送方只需重传未被确认的分段。但SACK 是 TCP 的可选功能(需双方协商启用),而累积确认是默认机制。接收方同样会缓存失序分组(通过接收窗口实现),并在收到丢失分组后按序交付。

超时间隔加倍

在 TCP 协议中,超时间隔加倍(Exponential Backoff) 是一种应对网络拥塞或丢包的重要机制,属于超时重传策略的一部分。当 TCP 发送方多次尝试重传数据仍失败时,会逐步指数级增大超时时间,避免因频繁重传加剧网络拥塞。

当 TCP 发送一个报文段后,会启动一个定时器。若在 RTO 时间内未收到该报文段的确认(ACK),则认为报文段丢失,触发重传

首次超时按正常 RTO 值重传,后续超时每次重传后,将 RTO 值翻倍(即指数级增长)。为避免 RTO 无限增长,TCP 通常设置上限(如 64 秒)。当 RTO 达到上限后,继续重传但不再增加 RTO。

超时间隔加倍避免网络拥塞,若每次超时都以固定时间重传,可能导致大量重传报文段同时涌入网络,加剧拥塞(如 “拥塞崩溃”)。指数退避通过减缓重传频率,给网络留出恢复时间。

区分临时丢包和持续问题:

  • 临时丢包(如网络抖动):较小的 RTO 即可快速恢复。
  • 持续丢包(如链路故障):需要更长的 RTO 避免无效重传。

超时重传 → RTO指数级增长 → 降低重传频率 → 缓解网络拥塞 这一机制是 TCP自适应网络变化的关键,通过动态调整超时时间,在可靠性和效率之间找到平衡,尤其适用于高延迟或不稳定的网络环境。

快速重传

快速重传是 TCP 协议中用于快速恢复丢失报文段的机制,乱序不影响最终确认,但是会触发重传机制。通过 重复确认冗余ACK(Duplicate ACK) 触发重传,无需等待超时定时器到期,从而减少丢包导致的延迟。

接收方通过累加确认,只会确认按序到达的连续字节流末尾,未按序到达的字节会导致后续确认被阻断。

当接收方收到失序报文段时,会发送重复 ACK(即对最近连续收到的最高序号的确认)。发送方收到3 个重复 ACK,判定该序号的报文段丢失,立即重传,无需等待超时。

快速重传 = 3次重复ACK触发 + 立即重传丢失报文段 + 低延迟恢复传输 该机制是 TCP 实现可靠传输高吞吐量的核心技术之一,通过快速响应轻度丢包,显著提升了网络传输效率,尤其适用于实时性要求较高的场景。

流量控制

TCP流量控制为了防止发送方发送速率超过接收方处理能力,避免接收方缓冲区溢出导致丢包。通过动态调整发送窗口大小,使发送速率与接收方处理能力匹配。

核心机制:滑动窗口协议

  1. 接收窗口(Advertised Window, rwnd)

    • 接收方通过 ACK 报文携带rwnd字段,告知发送方自己当前可用的接收缓冲区大小(字节)。
    • 计算公式:rwnd = 接收缓冲区总大小 - 已占用空间
  2. 发送窗口(Send Window)

    • 发送方根据接收方的rwnd动态调整自己的发送窗口大小,确保已发送但未确认的数据量 ≤ rwnd
    • 发送窗口大小 = min (rwndcwnd),其中cwnd为拥塞窗口(由拥塞控制决定)。

初始协商:连接建立时,双方通过 SYN 报文交换初始窗口大小(默认值通常为 4KB)。

动态调整:接收方每处理一批数据,通过 ACK 报文更新rwnd。发送方根据最新rwnd调整发送窗口,控制后续发送速率。

零窗口通知:当接收方缓冲区已满,rwnd = 0,发送方暂停发送,进入 ** 窗口探查(Window Probe)** 状态。

窗口探查:发送方定期发送窗口探测报文(1 字节数据),触发接收方回复最新rwnd,避免死锁。

该机制通过接收窗口实现端到端的速率匹配,确保接收方不会因过载而丢包。UDP没有流量控制,报文段由于缓存溢出可能在接收方丢失。

TCP连接管理 

我们先来详细看一下客户端如何三次握手和服务器建立TCP连接以及四次挥手安全断开连接:

三次握手

1. 客户端 → 服务器:SYN 包
  • 动作
    客户端向服务器发送一个SYN 包(TCP 首部中的 SYN 标志位 = 1),表示请求建立连接。
  • 携带信息
    • 初始序列号(ISN, Initial Sequence Number):客户端随机生成的一个 32 位序列号(如x),用于标识客户端发送的数据字节流起点。
    • 可选参数:如最大段大小(MSS)、窗口缩放因子等。
  • 状态变化
    客户端进入SYN_SENT状态,等待服务器响应。
2. 服务器 → 客户端:SYN+ACK 包
  • 动作
    服务器收到 SYN(同步) 包后,向客户端发送一个SYN+ACK 包(SYN 和 ACK 标志位同时置 1)。
  • 携带信息
    • 服务器的初始序列号(ISN):服务器随机生成的序列号(如y)。
    • 确认号(ACK Number):值为x+1,表示 “已收到客户端的 SYN 包,期望接收客户端下一个序列号为x+1的数据”。
    • 窗口大小(Window Size):服务器的接收窗口大小,告知客户端自己的缓冲区容量。
  • 状态变化
    服务器进入SYN_RCVD状态,等待客户端确认。
3. 客户端 → 服务器:ACK 包
  • 动作
    客户端收到 SYN+ACK 包后,向服务器发送一个ACK 包(ACK 标志位 = 1),SYN=0。
  • 携带信息
    • 确认号:值为y+1,表示 “已收到服务器的 SYN 包,期望接收服务器下一个序列号为y+1的数据”。
    • 序列号:客户端使用x+1作为本次 ACK 的序列号(因 SYN 包本身占用一个序列号)。
  • 状态变化
    客户端和服务器均进入ESTABLISHED状态,连接建立完成,开始数据传输。

四次挥手

1. 主动关闭方 → 被动关闭方:FIN 包
  • 场景
    假设客户端主动发起关闭(也可以是服务器主动关闭)。
  • 动作
    客户端向服务器发送一个FIN 包(TCP 首部中的 FIN 标志位 = 1),表示 “我已无数据要发送,可以关闭连接”。
  • 携带信息
    • 序列号(Seq):客户端当前的序列号u(FIN 包本身占用一个序列号,类似 SYN 包)。
  • 状态变化
    客户端进入FIN_WAIT_1状态,等待服务器的确认。
2. 被动关闭方 → 主动关闭方:ACK 包
  • 动作
    服务器收到 FIN 包后,立即向客户端发送一个ACK 包(ACK 标志位 = 1),表示 “已收到关闭请求,正在处理剩余数据”。
  • 携带信息
    • 确认号(Ack):值为u+1,表示 “已确认收到客户端的 FIN 包”。
    • 序列号(Seq):服务器当前的序列号v(未被 FIN 中断,继续沿用之前的序号)。
  • 状态变化
    服务器进入CLOSE_WAIT状态(半关闭状态),此时服务器仍可向客户端发送剩余数据,客户端仍需接收。
    客户端收到 ACK 后,进入FIN_WAIT_2状态,等待服务器发送 FIN 包。
3. 被动关闭方 → 主动关闭方:FIN 包
  • 动作
    当服务器确认已发送完所有数据后,向客户端发送第二个FIN 包(FIN 标志位 = 1),表示 “我已无数据可发送,正式请求关闭连接”。
  • 携带信息
    • 序列号(Seq):服务器的下一个序列号w(通常w = v + 已发送数据字节数,若中间无新数据,则w = v)。
  • 状态变化
    服务器进入LAST_ACK状态,等待客户端的最终确认。
    客户端收到第二个 FIN 后,进入TIME_WAIT状态。
4. 主动关闭方 → 被动关闭方:ACK 包
  • 动作
    客户端收到服务器的 FIN 包后,向服务器发送最后一个ACK 包,表示 “已确认关闭请求”。
  • 携带信息
    • 确认号(Ack):值为w+1,确认服务器的 FIN 包。
    • 序列号(Seq):客户端的下一个序列号u+1(FIN_WAIT_2 状态时序列号未变化,因无新数据发送)。
  • 状态变化
    • 客户端:发送 ACK 后进入TIME_WAIT状态,并在等待2 倍最大段生存时间(2MSL)后最终进入CLOSED状态。
    • 服务器:收到 ACK 后立即进入CLOSED状态,连接彻底关闭。

客户TCP经历的典型TCP状态序列:

服务器端TCP经历的典型TCP状态序列: 

 为什么必须要三次握手?

  1. 双向确认连接可用性
    • 客户端确认服务器 “能接收数据 + 能发送数据”。
    • 服务器确认客户端 “能接收数据 + 能发送数据”。
  2. 同步初始序列号(Seq)
    避免历史残留报文(延迟到达的旧连接数据包)干扰新连接。
为什么不能用两次握手?

假设改为两次握手(客户端→服务器:SYN;服务器→客户端:SYN+ACK):
存在的风险:

  1. 旧连接残留报文导致的资源浪费
    • 客户端发送的旧 SYN 报文(如因网络延迟滞留)被服务器误认为是新连接请求。
    • 服务器返回 SYN+ACK 并分配资源,但客户端实际未发起新连接,导致服务器端资源(如连接队列、内存)浪费(“半开连接” 问题)。
  2. 单向确认不完整
    • 服务器仅能确认客户端 “能发送数据”,但无法确认客户端 “能接收数据”。
    • 若客户端实际无法接收(如接收缓冲区已满),服务器发送的数据会被丢弃,导致连接不可靠。

结论:两次握手无法避免旧报文干扰,且无法完成双向确认,因此不可行。

四次或更多次握手可行吗?

理论上可行,但存在明显缺陷:

  1. 效率低下
    每增加一次握手,就多一次往返时延(RTT)。例如四次握手需 2 倍 RTT,而三次握手仅需 1.5 倍 RTT,对于高延迟网络(如卫星通信),效率损失显著。
  2. 无额外收益
    三次握手已能完成双向确认和序列号同步,多余的握手次数不会提升可靠性,反而增加协议复杂度。

结论:三次握手是效率与可靠性的最优平衡,多于三次握手无实际意义。

为什么要四次挥手?

TCP 连接是全双工的(双向独立传输),全双工特性要求双向数据流独立关闭:

  1. 允许双向数据流独立关闭
    一方(如客户端)先发送 FIN 包请求关闭 “主动关闭方→被动关闭方” 的数据流,另一方仍可继续发送数据。
  2. 确保数据完整传输
    被动关闭方需先确认收到 FIN 包(避免丢包),待自身数据发送完毕后,再发送 FIN 包关闭反向数据流,确保无数据丢失。
为什么不能用三次挥手?

假设尝试合并两次挥手为一次(如服务器在 ACK 包中同时携带 FIN 标志):
存在的问题:

  • 被动关闭方可能尚未完成数据发送
    服务器收到客户端的 FIN 包后,需先确认(ACK),但此时服务器可能仍有数据未发送完毕。若直接在 ACK 中携带 FIN,会导致服务器被迫中断数据传输,违反 “允许单向数据流持续” 的原则。

示例场景:
客户端发送 FIN 请求关闭 “客户端→服务器” 方向,服务器回复 ACK(确认收到 FIN),并继续发送剩余数据。待数据发送完毕后,服务器再发送 FIN 关闭 “服务器→客户端” 方向。这一过程必须分为两次独立的报文(ACK 和 FIN),因此无法合并为三次挥手。

两次挥手可行吗?

仅在一种特殊场景下可行:被动关闭方在收到 FIN 包时,自身已无数据需要发送。此时可将 ACK 和 FIN 合并为一个报文,形成两次挥手:

  1. 客户端→服务器:FIN(请求关闭)。
  2. 服务器→客户端:FIN+ACK(确认关闭并请求反向关闭)。
  3. 客户端→服务器:ACK(确认反向关闭)。
    但这是特例,而非通用情况,因为 TCP 无法保证被动关闭方在收到 FIN 时恰好无数据待发。

结论:通用场景下必须四次挥手,仅特殊场景可简化为三次,但无法普遍适用两次。

✍🏻✍🏻✍🏻.

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

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

相关文章

SpringAI系列 - 升级1.0.0

目录 一、调整pom二、MessageChatMemoryAdvisor调整三、ChatMemory get方法删除lastN参数四、QuestionAnswerAdvisor调整Spring AI发布1.0.0正式版了😅 ,搞起… 一、调整pom <properties><java.version>17</java.version><spring-ai.version>

前端高频面试题2:JavaScript/TypeScript

1.什么是类数组对象 一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象&#xff0c;类数组对象和数组类似&#xff0c;但是不能调用数组的方法。常见的类数组对象有 arguments 和 DOM 方法的返回结果&#xff0c;还有一个函数也可以被看作是类数组对象&#xff…

Spring Security入门:创建第一个安全REST端点项目

项目初始化与基础配置 创建基础Spring Boot项目 我们首先创建一个名为ssia-ch2-ex1的空项目(该名称与配套源码中的示例项目保持一致)。项目需要添加以下两个核心依赖: org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-starter-secur…

秋招Day12 - 计算机网络 - UDP

说说TCP和UDP的区别&#xff1f; TCP使用无边界的字节流传输&#xff0c;可能发生拆包和粘包&#xff0c;接收方并不知道数据边界&#xff1b;UDP采用数据报传输&#xff0c;数据报之间相互独立&#xff0c;有边界。 应用场景方面&#xff0c;TCP适合对数据的可靠性要求高于速…

【QQ音乐】sign签名| data参数加密 | AES-GCM加密 | webpack (下)

1.目标 网址&#xff1a;https://y.qq.com/n/ryqq/toplist/26 我们知道了 sign P(n.data)&#xff0c;其中n.data是明文的请求参数 2.webpack生成data加密参数 那么 L(n.data)就是密文的请求参数。返回一个Promise {<pending>}&#xff0c;所以L(n.data) 是一个异步函数…

Codeforces Round 1028 (Div. 2)(A-D)

题面链接&#xff1a;Dashboard - Codeforces Round 1028 (Div. 2) - Codeforces A. Gellyfish and Tricolor Pansy 思路 要知道骑士如果没了那么这个人就失去了攻击手段&#xff0c;贪心的来说我们只需要攻击血量少的即可&#xff0c;那么取min比较一下即可 代码 void so…

【存储基础】存储设备和服务器的关系和区别

文章目录 1. 存储设备和服务器的区别2. 客户端访问数据路径场景1&#xff1a;经过服务器处理场景2&#xff1a;客户端直连 3. 服务器作为"中转站"的作用 刚开始接触存储的时候&#xff0c;以为数据都是存放在服务器上的&#xff0c;服务器和存储设备是一个东西&#…

macOS 安装 Grafana + Prometheus + Node Exporter

macOS 安装指南&#xff1a;Grafana Prometheus Node Exporter 目录简介&#x1f680; 快速开始 安装 Homebrew1. 安装 Homebrew2. 更新 Homebrew 安装 Node Exporter使用 Homebrew 安装验证 Node Exporter 安装 Prometheus使用 Homebrew 安装验证安装 安装 Grafana使用 Home…

不可变集合类型转换异常

记录一个异常&#xff1a;class java.util.ImmutableCollections$ListN cannot be cast to class java.util.ArrayList (java.util.ImmutableCollections$ListN and java.util.ArrayList 文章目录 1、原因2、解决方式一3、解决方式二4、关于不可变集合的补充4.1 JDK8和9的对比4…

【DAY37】早停策略和模型权重的保存

内容来自浙大疏锦行python打卡训练营 浙大疏锦行 知识点&#xff1a; 过拟合的判断&#xff1a;测试集和训练集同步打印指标模型的保存和加载 仅保存权重保存权重和模型保存全部信息checkpoint&#xff0c;还包含训练状态 早停策略 作业&#xff1a; 对信贷数据集训练后保存权…

【Zephyr 系列 3】多线程与调度机制:让你的 MCU 同时干多件事

好的,下面是Zephyr 系列第 3 篇:聚焦 多线程与调度机制的实践应用,继续面向你这样的 Ubuntu + 真板实战开发者,代码清晰、讲解通俗、结构规范,符合 CSDN 高质量博客标准。 🧠关键词:Zephyr、线程调度、k_thread、k_sleep、RTOS、BluePill 📌适合人群:想从裸机开发进…

实现RabbitMQ多节点集群搭建

目录 引言 一、环境准备 二、利用虚拟机搭建 ​ 三、镜像集群配置 四、HAProxy实现负载均衡(主用虚拟机操作) 五、测试RabbitMQ集群搭建情况 引言 在现代分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff09;扮演着至关重要的角色,而 RabbitMQ 作为…

异步上传石墨文件进度条前端展示记录(采用Redis中String数据结构实现-苏东坡版本)

昔者&#xff0c;有客临门&#xff0c;亟需自石墨文库中撷取卷帙若干。此等文册&#xff0c;非止一卷&#xff0c;乃累牍连篇&#xff0c;亟需批量转置。然吾辈虑及用户体验&#xff0c;当效东坡"腹有诗书气自华"之雅意&#xff0c;使操作如行云流水&#xff0c;遂定…

Axure 基础入门

目录 认识产品经理 项目团队* 基本概述 认识产品经理 A公司产品经理 B公司产品经理 C公司产品经理 D公司产品经理 产品经理工作范围 产品经理工作流程* 产品经理的职责 产品经理的分类 产品经理能力要求 产品工具 产品体验报告 原型设计介绍 原型设计概述 为…

零基础学习计算机网络编程----socket实现UDP协议

本章将会详细的介绍如何使用 socket 实现 UDP 协议的传送数据。有了前面基础知识的铺垫。对于本章的理解将会变得简单。将会从基础的 Serve 的初始化&#xff0c;进阶到 Client 的初始化&#xff0c;以及 run。最后实现一个简陋的小型的网络聊天室。 目录 1.UdpSever.h 1.1 构造…

普中STM32F103ZET6开发攻略(二)

接上文&#xff1a;普中STM32F103ZET6开发攻略&#xff08;一&#xff09;-CSDN博客 各位看官老爷们&#xff0c;点击关注不迷路哟。你的点赞、收藏&#xff0c;一键三连&#xff0c;是我持续更新的动力哟&#xff01;&#xff01;&#xff01; 目录 接上文&#xff1a;普中…

用提示词写程序(3),VSCODE+Claude3.5+deepseek开发edge扩展插件V2

edge扩展插件;筛选书签,跳转搜索,设置背景 链接: https://pan.baidu.com/s/1nfnwQXCkePRnRh5ltFyfag?pwd86se 提取码: 86se 导入解压的扩展文件夹: 导入扩展成功: edge扩展插件;筛选书签,跳转搜索,设置背景

电脑桌面便签软件哪个好?桌面好用便签备忘录推荐

在日常办公中&#xff0c;一款优秀的桌面便签工具能显著提升工作效率。面对市面上琳琅满目的选择&#xff0c;不少用户都难以抉择。如果你正在寻找一款兼具轻量化与多功能性的便签软件&#xff0c;那么集实用性与便捷性于一身的"好用便签"&#xff0c;或许就是你的理…

性能优化 - 工具篇:基准测试 JMH

文章目录 Pre引言1. JMH 简介2. JMH 执行流程详解3. 关键注解详解3.1 Warmup3.2 Measurement3.3 BenchmarkMode3.4 OutputTimeUnit3.5 Fork3.6 Threads3.7 Group 与 GroupThreads3.8 State3.9 Setup 与 TearDown3.10 Param3.11 CompilerControl 4. 示例代码与分析4.1 关键点解读…

2025年十大AI幻灯片工具深度评测与推荐

我来告诉你一个好消息。 我们已经亲自测试和对比了市面上最优秀的AI幻灯片工具&#xff0c;让你无需再为选择而烦恼。 得益于AI技术的飞速发展&#xff0c;如今你可以快速制作出美观、专业的幻灯片。 这些智能平台的功能远不止于配色美化——它们能帮你头脑风暴、梳理思路、…