【计网】TCP在可靠传输中都干了啥

文章目录

    • 1、概述
    • 2、校验和
    • 3、序列号和确认应答机制
    • 4、重传机制
      • 4.1、介绍
      • 4.2、超时重传
      • 4.3、快速重传
    • 5、滑动窗口协议
      • 5.1、介绍
      • 5.2、发送方的滑动窗口
      • 5.3、接收方的滑动窗口
    • 6、流量控制
    • 7、拥塞控制
      • 7.1、介绍
      • 7.2、慢开始
      • 7.3、拥塞避免
      • 7.4、快重传和快恢复

1、概述

TCP 是面向连接的、可靠的、基于字节流的传输层通信协议,处于OSI模型的第四层传输层。

img

那么什么是可靠传输呢?可靠传输就是保证接收方收到的字节流和发送方发出的字节流是完全一样的。也就是说,通过 TCP 连接传输的数据,无差错、不丢失、不重复、并且按序到达。

网络层是没有可靠传输机制的,尽自己最大的努力进行交付。而传输层使用 TCP 实现可靠传输,TCP 保证可靠传输的机制有如下几种:

  • 校验和 Checksum
  • 序列号和确认应答机制
  • 重传机制
  • 流量控制(滑动窗口协议)
  • 拥塞控制

2、校验和

所谓 TCP 的校验和(Checksum)就是说:由发送端计算待发送 TCP 报文段的校验和,然后接收端对接收到的 TCP 报文段验证其校验和(TCP 的校验和是一个端到端的校验和)。其目的是为了发现 TCP 的首部和数据在发送端到接收端之间是否发生了变动。如果接收方检测到校验和有差错,则该 TCP 报文段会被直接丢弃

TCP 在计算校验和时,需要加上一个 12 字节的伪首部。伪首部的数据是从 IP 数据报头获取的,共有 12 字节,包含如下信息:源 IP 地址、目的 IP 地址、保留字节 (置 0)、传输层协议号 (TCP 是 6)、TCP 报文长度 (首部 + 数据):

image-20230727163923854

3、序列号和确认应答机制

这个机制类似于问答的形式。比如在课堂上老师会问你“明白了吗?”,假如你没有隔一段时间没有回应或者你说不明白,那么老师就会重新讲一遍。

其实计算机的确认应答机制也是一样的,发送端发送信息给接收端,接收端会回应一个包,这个包就是应答包(ACK),而序列号则是标识发送者是谁。

SYN + ACK 报文

4、重传机制

4.1、介绍

在错综复杂的网络,并不一定能够顺利的传输报文,报文存在丢失的可能性。报文丢失的可能因素有很多种,包括应用故障,路由设备过载,或暂时的服务宕机。报文级别速度是很高的,通常来说报文的丢失是暂时的,因此 TCP 能够发现和恢复报文丢失显得尤为重要

重传机制是 TCP 最基本的错误恢复功能,常见的重传机制有如下:

  • 超时重传
  • 快速重传

4.2、超时重传

超时重传是最常看到的一种重传机制,如在之前提及到的《【计网】什么是三次握手四次挥手》中,便多次提及到了在三次握手四次挥手中若报文丢失或超时变回触发超时重传。

超时重传就是 TCP 发送方在发送报文的时候,设定一个定时器,如果在规定的时间内没有收到接收方发来的 ACK 确认报文,发送方就会重传这个已发送的报文段。

超时重传时间我们一般用 RTO(Retransmission Timeout)来表示,RTT (Round-Trip Time 往返时延)就是数据从网络一端传送到另一端所需的时间,也就是报文段的往返时间。

显然,超时重传时间 RTO 的值应该略大于报文往返 RTT 的值

image-20230727213721975

我们可以假想一下,如果超时重传时间 RTO 远大于或小于 RTT,会发生什么情况:

  • RTO 远大于 RTT:网络的空闲时间增大,降低了网络传输效率。即如果真的丢失了,等待的时间过长,原本一分钟能干五碗饭,在RTO远大于RTT后,一分钟只能干两碗了,使得两端之间的网络传输效率变差;
  • RTO 小于 RTT:不必要的重传,导致网络负荷增大,甚至无法完成正常的网络传输。简单来说就是,如果通过TCP传输一个数据包最快需要2ms,但是由于RTO小于RTT,假设设置RTO为1ms,那么在这个数据包还未传输到接收方时便已经触发超时重传机制,导致永远无法完成该次网络传输。

image-20230727213955298

如果超时重传的数据又超时了该怎么办呢?TCP 的策略是重传的超时间隔加倍

也就是说,每进行一次超时重传,都会将下一次重传的超时时间间隔设为先前值的两倍

超时触发重传存在的问题是,超时周期可能相对较长。有没有一种机制可以减少超时重传的等待时间呢?于是快速重传机制应运而生。

4.3、快速重传

快速重传(Fast Retransmit)机制不以时间为驱动,而是以数据驱动重传

快速重传机制的原理:每当接收方收到比期望序号大的失序报文段到达时,就向发送方发送一个冗余 ACK,指明下一个期待字节的序号。简单来说,就是接收方收到的数据包如果不是按照顺序来的,不管是乱序还是丢失,也会给客户端回复冗余ACK,用来标记到发送到哪里的时候乱序或丢失了。

对于何时重传有这么一个阈值,当冗余ACK达到3个时,便会触发重传,即发现三个乱序或丢失的数据包时,便会触发快速重传。

注意:是冗余ACK达到3个,不是收到3个重复的ACK便会触发重传,因为除了3个冗余ACK外,还有一个是最开始的正确的ACK,所以重复的ACK是4个,其中冗余ACK3个,有1个是正确的ACK

举个例子:发送方已经发送 1、2、3、4、5报文段

  • 接收方收到报文段 1,返回 1 的 ACK 确认报文(确认号为报文段 2 的第一个字节)
  • 接收方收到报文段 3,仍然返回 1 的 ACK 确认报文(确认号为报文段 2 的第一个字节)
  • 接收方收到报文段 4,仍然返回 1 的 ACK 确认报文(确认号为报文段 2 的第一个字节)
  • 接收方收到报文段 5,仍然返回 1 的 ACK 确认报文(确认号为报文段 2 的第一个字节)
  • 接收方收到 3 个对于报文段 1 的冗余 ACK,认为报文段 2 丢失,于是重传报文段 2
  • 最后,接收方收到了报文段 2,此时因为报文段 3、4、5 都收到了,所以返回 6 的 ACK 确认报文(确认号为报文段 6 的第一个字节)

image-20230728093730872

5、滑动窗口协议

5.1、介绍

我们都知道 TCP 是每发送一个数据,都要进行一次确认应答。当上一个数据包收到了应答了, 再发送下一个。

这个模式就有点像我和你面对面聊天,你一句我一句。但这种方式的缺点是效率比较低的。

如果你说完一句话,我在处理其他事情,没有及时回复你,那你不是要干等着我做完其他事情后,我回复你,你才能说下一句话,很显然这不现实。

按数据包进行确认应答

所以,这样的传输方式有一个缺点:数据包的往返时间越长,通信的效率就越低

为解决这个问题,TCP 引入了窗口这个概念。即使在往返时间较长的情况下,它也不会降低网络通信的效率。

那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值

窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。

假设窗口大小为 3 个 TCP 段,那么发送方就可以「连续发送」 3 个 TCP 段,并且中途若有 ACK 丢失,可以通过「下一个确认应答进行确认」。

image-20230728103719521

图中的 ACK 600 确认应答报文丢失,也没关系,因为可以通过下一个确认应答进行确认,只要发送方收到了 ACK 700 确认应答,就意味着 700 之前的所有数据「接收方」都收到了。这个模式就叫累计确认或者累计应答

那么窗口大小由哪一方决定?

TCP 头里有一个字段叫 Window,也就是窗口大小。

这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。

所以,通常窗口的大小是由接收方的窗口大小来决定的。

发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。

5.2、发送方的滑动窗口

我们先来看看发送方的窗口,下图就是发送方缓存的数据,根据处理的情况分成四个部分,其中深蓝色方框是发送窗口,紫色方框是可用窗口:

  • #1 是已发送****收到 ACK确认的数据:1~31 字节
  • #2 是已发送****未收到 ACK确认的数据:32~45 字节
  • #3 是未发送但总大小**接收方处理范围**(接收方还有空间):46~51字节
  • #4 是未发送但总大小**超过**接收方处理范围(接收方没有空间):52字节以后

img

在下图,当发送方把数据「全部」都一下发送出去后,可用窗口的大小就为 0 了,表明可用窗口耗尽,在没收到 ACK 确认之前是无法继续发送数据了。
可用窗口耗尽

在下图,当收到之前发送的数据 32~36 字节的 ACK 确认应答后,如果发送窗口的大小没有变化,则滑动窗口往右边滑动 5 个字节,因为有 5 个字节的数据被应答确认,接下来 52~56 字节又变成了可用窗口,那么后续也就可以发送 52~56 这 5 个字节的数据了。

32 ~ 36 字节已确认

那么程序是如何表示发送方的四个部分的呢?

TCP 滑动窗口方案使用三个指针来跟踪在四个传输类别中的每一个类别中的字节。其中两个指针是绝对指针(指特定的序列号),一个是相对指针(需要做偏移):

  • SND.WND:表示发送窗口的大小(大小是由接收方指定的);
  • SND.UNASend Unacknoleged):是一个绝对指针,它指向的是已发送但未收到确认第一个字节的序列号,也就是 #2 的第一个字节。
  • SND.NXT:也是一个绝对指针,它指向未发送但可发送范围第一个字节的序列号,也就是 #3 的第一个字节。可用窗口大小 = SND.WND -(SND.NXT - SND.UNA)
  • 指向 #4 的第一个字节是个相对指针,它需要 SND.UNA 指针加上 SND.WND 大小的偏移量,就可以指向 #4 的第一个字节了。

image-20230728104757655

5.3、接收方的滑动窗口

接下来我们看看接收方的窗口,接收窗口相对简单一些,根据处理的情况划分成三个部分:

  • #1 + #2 是已成功接收并确认的数据(等待应用进程读取);
  • #3 是未收到数据但可以接收的数据;
  • #4 未收到数据且不可以接收的数据;

image-20230728105530364

其中三个接收部分,使用两个指针进行划分:

  • RCV.WND:表示接收窗口的大小,它会通告给发送方。
  • RCV.NXT:是一个指针,它指向期望从发送方发送来的下一个数据字节的序列号,也就是 #3 的第一个字节。
  • 指向 #4 的第一个字节是个相对指针,它需要 RCV.NXT 指针加上 RCV.WND 大小的偏移量,就可以指向 #4 的第一个字节了。

那么接收窗口和发送窗口的大小是相等的吗?

答案是并不完全相等,接收窗口的大小是约等于发送窗口的大小的。

因为滑动窗口并不是一成不变的。比如,当接收方的应用进程读取数据的速度非常快的话,这样的话接收窗口可以很快的就空缺出来。那么新的接收窗口大小,是通过 TCP 报文中的 Windows 字段来告诉发送方。那么这个传输过程是存在时延的,所以接收窗口和发送窗口是约等于的关系。

6、流量控制

想象一下这个场景:主机 A 一直向主机 B 发送数据,不考虑主机 B 的接收能力,则可能导致主机 B 的接收缓冲区满了而无法再接收数据,从而导致大量的数据丢包,引发重传机制。而在重传的过程中,若主机 B 的接收缓冲区情况仍未好转,则会将大量的时间浪费在重传数据上,降低传送数据的效率。

所以引入了流量控制机制,主机 B 通过告诉主机 A 自己接收缓冲区的大小,来使主机 A 控制发送的数据量。总结来说:所谓流量控制就是控制发送方发送速率,保证接收方来得及接收

TCP 实现流量控制主要就是通过 滑动窗口协议

在前面说到滑动窗口的大小是由接收方告知发送方的,那么是如何告知的呢?在《【计网】什么是三次握手四次挥手》中其实有展示过只是未提及,在数据报文中是存在这么一个16位的 窗口大小 Window 字段。

该字段的含义是指自己接收缓冲区的剩余大小,于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。

因此,通常来说窗口大小是由接收方来决定的

image-20230728110948007

接收方会在发送 ACK 确认应答报文时,将自己的即时窗口大小(接收窗口 rwnd)填入,并跟随 ACK 报文一起发送出去。而发送方根据接收到的 ACK 报文中的窗口大小的值改变自己的发送速度。如果接收到窗口大小的值为 0,那么发送方将停止发送数据。并定期的向接收端发送窗口探测数据段,提醒接收端把窗口大小告诉发送端。

image-20230728111325212

7、拥塞控制

7.1、介绍

所谓拥塞就是说:在某段时间,对网络中某一资源的需求超过了该资源所能提供的可用部分(即 需大于供),网络的性能变差。

如果网络出现拥塞,TCP 报文可能会大量丢失,此时就会大量触发重传机制,从而导致网络拥塞程度更高,严重影响传输。

其实只要「发送方」没有在规定时间内接收到 ACK 应答报文,也就是触发了重传机制,就会认为网络出现了拥塞。

因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同

流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度,防止过多的数据注入到网络中。

为了调节发送方所要发送数据的量,定义了「拥塞窗口 cwnd」的概念。拥塞窗口是发送方维护的一个状态变量,它会根据网络的拥塞程度动态变化

  • 只要网络中出现了拥塞,cwnd 就会减少;
  • 若网络中没有出现拥塞,cwnd 就会增大。

引入拥塞窗口概念之前,发送窗口大小和接收窗口大小基本是相等的关系,即取决于接收窗口大小引入拥塞窗口后,发送窗口的大小就等于拥塞窗口和接收窗口的最小值

7.2、慢开始

慢开始的思路就是:TCP 在刚建立连接完成后,如果立即把大量数据字节注入到网络,那么很有可能引起网络阻塞。好的方法是先探测一下,逐步提高发送数据包的数量,即由小到大逐渐增大拥塞窗口数值。cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍(指数增长)。

image-20230728112020945

当然不能一直执行慢启动,这里会设置一个慢启动轮限 ssthresh 状态变量:

  • cwnd < ssthresh 时,继续使用慢启动算法
  • cwnd >= ssthresh 时,开始使用拥塞避免算法

7.3、拥塞避免

拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢增大,即每经过一个往返时间 cwnd 加 1

注意,无论是慢开始阶段还是拥塞避免,只要出现了网络拥塞(触发超时重传机制),慢开始轮限 sshresh 和 拥塞窗口大小 cwnd 的值都会发生变化(乘法减小):

  • ssthresh 设为 cwnd/2
  • cwnd 重置为 1

由于拥塞窗口大小重置为 1 了,所以就会重新开始执行慢启动算法。

image-20230728112600253

7.4、快重传和快恢复

快速重传和快速恢复算法一般同时使用。当触发快速重传机制,即接收方收到三个重复的 ACK 确认的时候,就会执行快重传算法(触发快速重传机制和超时重传机制的情况不同,TCP 认为触发快速重传的情况并不严重,因为大部分没丢,只丢了一小部分),快速重传做的事情有:

  • 阻塞窗口减半,即cwnd = cwnd/2
  • 慢开始轮限 = 阻塞窗口,即ssthresh = cwnd
  • 重新进入拥塞避免阶段

后来的 快速恢复 算法是在上述的“快速重传”算法后添加的,当收到 3 个重复ACK时,TCP 最后进入的不是拥塞避免阶段,而是快速恢复阶段。

快速恢复的思想是数据包守恒原则,即同一个时刻在网络中的数据包数量是恒定的,只有当旧数据包离开了网络后,才能向网络中发送一个新数据包,如果发送方收到一个重复的 ACK,那么根据 TCP 的 ACK 机制就表明有一个数据包离开了网络,于是 cwnd 加 1。如果能够严格按照该原则那么网络中很少会发生拥塞,事实上拥塞控制的目的也就在修正违反该原则的地方。

具体来说快速恢复的主要步骤:

  • cwnd 设置为 ssthresh 的值加 3,然后重传丢失的报文段,加 3 的原因是因为收到 3 个重复的 ACK,表明有 3 个旧数据包离开了网络;
  • 再收到重复的 ACK 时,拥塞窗口 cwnd 增加 1
  • 当收到新的数据包的 ACK 时,把 cwnd 设置为第一步中的 ssthresh 的值。原因是因为该 ACK 确认了新的数据,说明从重复 ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态。

image-20230728113411428

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

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

相关文章

lib-flexible修改配置适配更多不同分辨率

找到设置宽度的地方 然后根据你的屏幕最大多大呀&#xff0c;最小多小呀设置一下 if (width / dpr < 1980) { width 1980 * dpr; } else if (width / dpr > 5760) { width 5760 * dpr; }

https://app.hackthebox.com/machines/Sau

https://app.hackthebox.com/machines/Sau https://app.hackthebox.com/machines/Sau1.info collecting └─$ nmap -A 10.10.11.224 -T4 Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-30 15:36 HKT Nmap scan report for 10.10.11.224 (10.10.11.224) Host is up (…

全局ip代理安全吗? 手机设置全局代理方法详解

全局IP代理并不一定是安全的&#xff0c;因为全局IP代理会将所有网络流量都通过代理服务器进行转发&#xff0c;包括敏感信息和隐私数据。如果代理服务器受到黑客攻击或存在安全漏洞&#xff0c;可能会导致数据泄露和其他安全问题。因此&#xff0c;在使用全局IP代理时&#xf…

Spring Boot实践四 --集中式缓存Redis

随着时间的积累&#xff0c;应用的使用用户不断增加&#xff0c;数据规模也越来越大&#xff0c;往往数据库查询操作会成为影响用户使用体验的瓶颈&#xff0c;此时使用缓存往往是解决这一问题非常好的手段之一。Spring 3开始提供了强大的基于注解的缓存支持&#xff0c;可以通…

【Leetcode】62.不同路径

一、题目 1、题目描述 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示例1: 输入:m = 3, n = 7 输出:…

AD21原理图的高级应用(六)原理图设计片段的使用

&#xff08;六&#xff09;原理图设计片段的使用 Altium Designer 的片段功能可以很方便地重复使用一些单元模块,其中包括原理图的电路模块、PCB(包括布线)和代码模块。例如在工程中需要设计电源模块,而别的工程中又恰好有比较完善的电源模块,这时就可以通过片段功能重复地使用…

京东技术专家首推:Spring 微服务架构设计,GitHub 星标 128K

前言 本书提供了实现大型响应式微服务的实用方法和指导原则&#xff0c;并通过示例全面 讲解如何构建微服务。本书深入介绍了 Spring Boot、Spring Cloud、 Docker、Mesos 和 Marathon&#xff0c;还会教授如何用 Spring Boot 部署自治服务&#xff0c;而 无须使用重量级应用服…

03_使用execle表生成甘特图

背景 每次排期都需要话很多时间 很可能排期还不对头 这时候需要一个表能看到 1.什么时候项目结束 开始 转阶段 2.当前手上的活能不能做完 当前阶段手上有多少活 3.产品经理每次修改完计划迅速排期 甘特图生成 execle表生成 1.需要使用亿图创建甘特图 2.把当前的甘特图数据进…

TextClamp for Vue3.0(Vue3.0的文本展开收起组件)

呦&#xff01;大家好&#xff0c;好久没有更新博客了&#xff0c;最近实现了一个一直想自己完成的一个东西&#xff0c;就是文本的展开收起组件&#xff0c;以前项目需要用到&#xff0c;自己实现一个又太繁琐&#xff0c;所以那个时候都是用的别人的轮子&#xff0c;现在自己…

在Ail Linux中手动配置IPv6

第一步&#xff0c;登录阿里云服务器控制台&#xff0c;在“概览”页面找到对应实例&#xff0c;然后单击实例ID。 第二步&#xff0c;在“实例详情”页面中的“网络信息”栏目中&#xff0c;可以发现“IPv6 地址”中没有数据&#xff0c;然后单击“专有网络”的专有网络ID。 第…

Pandas进阶修炼120题-第三期(金融数据处理,51-80题)

目录 往期内容&#xff1a;第一期&#xff1a;Pandas基础&#xff08;1-20题&#xff09;第二期&#xff1a;Pandas数据处理&#xff08;21-50题&#xff09; 第三期 金融数据处理51.使用绝对路径读取本地Excel数据方法一&#xff1a;双反斜杠绝对路径方法二&#xff1a;r 拓展…

TypeScript算法题实战——剑指 Offer篇(5)

目录 一、平衡二叉树1.1、题目描述1.2、题解 二、数组中数字出现的次数2.1、题目描述2.2、题解 三、数组中数字出现的次数 II3.1、题目描述3.2、题解 四、和为s的两个数字4.1、题目描述4.2、题解 五、和为s的连续正数序列5.1、题目描述5.2、题解 六、翻转单词顺序6.1、题目描述…

大数据技术之Hive2

目录标题 3、Hive 数据类型3.1 基本数据类型&#xff1a;3.2 集合数据类型&#xff1a;3.3 类型转化 4、DDL数据定义4.1 创建数据库4.2 查询数据库4.3 创建表4.4 管理表4.5 外部表4.6 管理表与外部表的相互转换4.7 分区表4.7.1 分区表基本操作4.7.2 分区表注意事项 4.7 修改表4…

小程序picker 在苹果手机不兼容 bug,按month时在iPhone 显示不正确及自动定位时间问题

如下图&#xff1a;点击弹出时间列表&#xff1a;日历控件点击选择显示1年1月 解决: 加上起始时间字段 <picker mode"date" value"{{date}}" start"1970-09-01" end"2030-09-01"></picker> 问题二&#xff1a; 还是&a…

leetcode 面试题 01.03. URL化

⭐️ 题目描述 &#x1f31f; leetcode链接&#xff1a;面试题 01.03. URL化 思路&#xff1a; 计算出空格的个数&#xff0c;我们可以知道最后一个字符的位置 endPos&#xff0c;再从后 end 向前遍历若不是空格正常拷贝&#xff0c;是空格则替换成 %20&#xff0c;最终当空格…

Unity 性能优化二:内存问题

目录 策略导致的内存问题 GFX内存 纹理资源 压缩格式 Mipmap 网格资源 Read/Write 顶点数据 骨骼 静态合批 Shader资源 Reserved Memory RenderTexture 动画资源 音频资源 字体资源 粒子系统资源 Mono堆内存 策略导致的内存问题 1. Assetbundle 打包的时候…

antd中的Cascader级联选择框怎么清空重置React

项目场景&#xff1a; React项目&#xff0c;使用antd中的Cascader级联选择框 问题描述&#xff1a; 通过其他按钮无法重置选择框中的项 原因分析&#xff1a;&#xff08;对应解决办法一和二&#xff09; 1、级联选择框的数据默认是根据options绑定的数组中的value值来进行…

深入浅出指南:Netty开发【NIO核心组件】

目录 ​Netty开发【NIO核心组件】 1.NIO基础概念 2.NIO核心组件 2.1.Channel&&Buffer简介 2.2.Selector 服务器的多线程版本 服务器的线程池版本 服务器的selector版本 2.3.Buffer 0.ByteBuffer的正确使用流程 1.ByteBuffer类型简介 2.ByteBuffer核心属性说…

【解惑笔记】树莓派+OpenCV+YOLOv5目标检测(Pytorch框架)

【学习资料】 子豪兄的零基础树莓派教程https://github.com/TommyZihao/ZihaoTutorialOfRaspberryPi/blob/master/%E7%AC%AC2%E8%AE%B2%EF%BC%9A%E6%A0%91%E8%8E%93%E6%B4%BE%E6%96%B0%E6%89%8B%E6%97%A0%E7%97%9B%E5%BC%80%E6%9C%BA%E6%8C%87%E5%8D%97.md#%E7%83%A7%E5%BD%95…

Qt6 Qt Quick UI原型学习QML第七篇

文章目录 效果演示QML语法 ClickableImageV2.qmlQML语法 EasingCurves.qml时钟小球滚动QML 源码## 时钟小球滚动QML解释 语法解释参考动画片动画元素应用动画可点击图像V2上升的物体第一个对象第二个对象第三个对象缓和曲线分组动画并行动画连续动画嵌套动画 效果演示 QML语法 …