当前位置: 首页 > news >正文

IO系列(十) -TCP 滑动窗口原理介绍(上)

一、摘要

之前在上分享网络编程知识文章的时候,有网友写下一条留言:“可以写写一篇关于 TCP 滑动窗口原理的文章吗?”。

当时没有立即回复,经过查询多方资料,发现这个 TCP 真的非常非常的复杂,就像一个清澈的小沟,你以为很浅,结果一脚踩下去,感觉深不可测。

虽然之前也总结过一些关于网络编程相关的技术知识,对于 TCP 协议栈也做过一些介绍,但是大体上都描述的比较简单,没有深入去了解,本篇在很大程度上弥补了我对计算机网络知识的空白。

话不多说,直接上干货!

二、TCP 数据传输

在之前的文章中我们了解到,TCP 协议能保证网络上的计算机之间可靠无差错的数据传输,比如上传文件、下载文件、浏览网页等都得益于它,实际的应用场景非常广泛。

与 TCP 协议一并称霸天下的还有 UDP 协议,不过 UDP 协议虽然传输效率更高,但是并不保证数据传输正确性,相比 TCP 要稍逊一些。

事实上,TCP 协议经过多年的发展,已经成为实现数据可靠传输的标准协议,所谓可靠,就是确保数据准确的、不重复、无延迟的到达目的地,那 TCP 协议是如何实现这些特点的呢?

其实要实现数据可靠传输,并不简单,因为要考虑异常的情况比较多,例如数据丢失、数据顺序混乱、网络拥堵等,如果不能解决这些问题,也就无从谈起可靠传输。

总的来说,TCP 协议是通过序列号、确认应答、重发控制、连接管理以及窗口控制等机制实现数据稳定可靠性的传输

以下是 TCP 协议的报文格式。

TCP 报文段包括协议首部和数据两部分,协议首部的固定部分是 20 个字节,头部是固定部分,后面是选项部分。

下面是报文段首部各个字段的含义:

  • 源端口号以及目的端口号:各占 2 个字节,端口是传输层和应用层的服务接口,用于寻找发送端和接收端的进程,一般来讲,通过端口号和IP地址,可以唯一确定一个 TCP 连接,在网络编程中,通常被称为一个 socket 接口。
  • 序号:Seq 序号,占 4 个字节。用来标识从 TCP 发送端向 TCP 接收端发送的数据字节流序号,发起方发送数据时对此进行标记。
  • 确认序号:Ack 序号,占 4 个字节,包含接受端所期望收到的下一个序号。只有 ACK 标记位为 1 时,确认序号字段才有效,因此,确认序号应该是上次已经成功收到数据字节序号加 1,即 Ack = Seq + 1。
  • 数据偏移:占 4 个字节,用于指出 TCP 首部长度。
  • 保留字段:占 6 位,暂时可忽略,值全为 0。
  • 六位标志位:值内容含义如下
    • URG(紧急):为1时表明紧急指针字段有效
    • ACK(确认):为1时表明确认号字段有效
    • PSH(推送):为1时接收方应尽快将这个报文段交给应用层
    • RST(复位):为1时表明TCP连接出现故障必须重建连接
    • SYN(同步):在连接建立时用来同步序号
    • FIN(终止):为1时表明发送端数据发送完毕要求释放连接
  • 窗口:占 2 个字节,用于流量控制和拥塞控制,表示当前接收缓冲区的大小。
  • 校验和:占 2 个字节,范围包括首部和数据两部分
  • 紧急指针:指出了紧急数据的末尾在报文段中的位置,和 URG 搭配使用
  • 选项和填充:是可选的,默认情况是不选。

计算机之间使用 TCP 协议进行传输数据时,每次连接都需要经过 3 个阶段:创建连接、数据传送和释放连接,即传输数据之前,在发送端和接收端建立逻辑连接、然后传输数据、最后断开连接,它保证两台计算机之间比较可靠的数据传输。

2.1、创建连接

当两个设备之间准备传输数据之前,TCP 会建立连接,创建连接的阶段需要三次握手,过程如下:

详细过程如下:

  • 第一次握手:客户端向服务器端发出连接请求,等待服务器确认
  • 第二次握手:服务器端收到请求后,向客户端回送一个确认,通知客户端收到了连接请求
  • 第三次握手:客户端再次向服务器端发送确认信息,确认连接

完成以上 3 次握手之后,可靠性连接建立完成,就可以进行数据传输了。

2.2、释放连接

当数据传输完毕之后,TCP 会释放连接,连接的释放需要四次挥手,过程如下:

  • 第一次挥手:客户端向服务器端发出请求切断连接,等待服务器确认
  • 第二次挥手:服务器端收到请求后,向客户端回送一个确认信息,并同意关闭请求
  • 第三次挥手:服务器端再次向客户端发出请求切断连接,等待客户端确认
  • 第四次挥手:客户端收到请求后,向服务器端回送一个确认信息,并同意关闭请求

完成以上 4 次挥手之后,连接释放完成。

2.3、数据传输过程

通过以上的介绍,我们可以描绘出一个简易版的 TCP 数据传输过程,如下图所示。

通过序列号与确认应答机制,是 TCP 实现数据可靠传输的方式之一,也是最为重要的基石

但是在复杂的网络环境下,并不一定能如上图所描述的那样顺利的进行数据传输,例如数据包丢失,针对这种问题,TCP 使用了重传机制来解决。

三、重传机制介绍

当网络不稳定的时候,很容易出现数据包丢失,TCP 采用了哪些重传手段来解决数据包丢失问题呢?

常见的重传方式有以下几种:

  • 超时重传
  • 快速重传
  • SACK
  • D-SACK
3.1、超时重传

超时重传,顾名思义,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发数据。

TCP 会在以下两种情况发生超时重传:

  • 发送的数据包丢失
  • 确认应答丢失

其中比较关键的就是超时重传时间如何来设定的问题。

我们先来看看正常的数据传输过程。

其中 RTT 指的是数据从网络一端传送到另一端所需的时间,也就是数据包发送出去的往返时间。

超时重传时间,我们以 RTO (Retransmission Timeout 超时重传时间)来表示。

当超时重传时间设定过大,会出现什么情况呢?如下图所示

当超时重传时间设定过小,又会出现什么情况呢?如下图所示

一路分析下来,可以得出如下结论:

  • 当超时重发时间 RTO 设置较大时,会出现数据传输效率差的现象,比如数据包丢失之后,需要等很长时间才重发,性能差;
  • 当超时重发时间 RTO 设置较小时,可能会出现并没有丢失包就重发,多次重发会造成网络拥堵,导致出现更多的超时,更多的超时意味着更多的重发;

因此可以得出一个结论,超时重发时间既不能设置过大,也不能设置过小,必须精准的计算。

以 Linux 操作系统为例,RTO 的计算过程如下!

  • 首先对 TCP 数据传输所需的往返时间,也就是 RTT 值进行采样,然后进行加权平均,算出一个平滑 RTT 的值,同时这个值随着网络状态会不断的变化。
  • 除了采样 RTT 值,还要记录 RTT 的波动变化,避免 RTT 的变化较大,难以发现

其中SRTT是计算平滑的RTT DevRTR是计算平滑的RTT与最新RTT的差距,在 Linux 下,通常α = 0.125β = 0.25μ = 1∂ = 4,至于这个数值是怎么算出的,答案就是大量的数据采集统计出来的。

实际算出来的超时重传时间RTO的值应该略大于报文往返RTT的值,符合预期值。

如果超时重发的数据,再次超时的时候,又需要重传的时候,TCP 的策略是超时间隔加倍。

也就是说,每当遇到一次超时重传的时候,会将下一次超时时间间隔设为先前值的两倍,多次超时说明网络环境差,不宜频繁反复重发。

3.2、快速重传

超时重传虽然能解决数据丢包的问题,但是超时重发时间有时候可能会较长,有没有一种更快的重传方式呢?

快速重传就是来补充超时重传机制中时间过长的问题

简单的说,快速重传不像超时重传那样通过时间来驱动重发,而是通过次数来驱动重发。

当收到报文重复的 ACK 数量,到达一定的阀值(一般为3),TCP 会在定时器过期之前,检查丢失的报文段并重传丢失的报文段。

大致的工作方式,可以用如下图来描述!

在上图,发送方向接受方发出了 1、2、3、4、5 份数据,大致执行的过程如下:

  • 第一份 Seq1 先送到了,接受方就 Ack 回 2,表示 seq 1 已经收到,准备接受下一个序列号为 2 的包
  • Seq2 因为某些原因没收到,Seq3 到达了,因为 Seq2 缺失,还是 Ack 回 2
  • 后面的 Seq4 和 Seq5 都到了,因为 Seq2 没有收到,还是 Ack 回 2
  • 发送端收到了三个 Ack = 2 的确认,知道了 Seq2 还没有收到,就会在定时器过期之前,重传丢失的 Seq2
  • 最后接收方收到了 Seq2,此时因为 Seq3,Seq4,Seq5 都收到了,于是 Ack 回 6 。

因此,快速重传的工作方式是当收到相同的 ACK 报文数量到达一个阀值,默认是 3,会在定时器过期之前,重传丢失的报文段。

快速重传机制弥补了超时重传机制中时间过长的问题,但是它依然面临着另外一个问题,那就是重传的时候,是重传之前的一个还是重传所有的包?

例如上面的例子,是重传 Seq2 呢?还是重传 Seq2、Seq3、Seq4、Seq5 呢?

根据 TCP 不同的实现,以上两种情况都有可能。

另外按照上文的分析,如果每发送一个数据,当收到确认应答再发送下一个数据包的传输模式下,基本上不会出现快速重传的可能。

关于快速重传的实际应用,我们会在滑动窗口中再次进行详解,目前只需要知道有这个方式就行。

3.3、SACK 方法

为了解决不知道该重传哪些 TCP 报文,天才师们想出来了SACK方法,英文全称:Selective Acknowledgment,也被称为选择性确认

具体实现就是需要在 TCP 头部选项字段里加一个 SACK 的东西,接受方可以将缓存的数据地图发送给发送方,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。

如下图,当发送方收到了三次同样的 ACK 确认报文,于是就会触发快速重发机制,通过 SACK 信息发现只有200~299这段数据丢失,会将丢失的片段进行重发,以便提升数据传输可靠性效率。

需要主要的是,如果要支持 SACK 机制,必须发送方和接受方都要支持。在 Linux 操作系统中,开发者可以通过net.ipv4.tcp_sack参数打开这个功能(Linux 2.4 后默认打开)。

3.4、Duplicate SACK 方法

最后再来讲讲 Duplicate SACK 方法,又称D-SACK,这个方法实现主要是使用 SACKACK来告诉发送方有哪些数据被重复接收了,以防止 TCP 反复的重发。

我们用个案例来介绍D-SACK的作用,例如 ACK 丢包的场景,如下图!

过程分析:

  • 发送方向接受方成功的发送了两个数据包,但是接受方发给发送方两个 ACK 确认应答都丢失了,发送方检查超时后,重传第一个数据包(100 ~ 199)
  • 接收方发现数据是重复收到的,于是回了一个ACK 300 SACK 100~199,告诉发送方100~299的数据早已被接收了,因为 ACK 都到300了,因此这个 SACK 可以称为D-SACK
  • 当发送方知道数据没有丢,是接收方的 ACK 确认报文丢了,就不会继续重发数据包了

使用D-SACK方法的好处,可以让发送方知道,是发出去的包丢了还是接收方回应的 ACK 包丢了,然后来决定是否需要继续重发包。

在 Linux 操作系统下,可以通过net.ipv4.tcp_dsack参数来开启/关闭这个功能(Linux 2.4 后默认打开)。

四、滑动窗口介绍

在上文中,我们有介绍到 TCP 协议的数据传输机制,当两台计算机之间建立连接之后,就可以进行传输数据了,TCP 每发送一个数据,都要进行一次确认应答,当上一个数据包收到了确认应答了, 再发送下一个,从而保证数据的可靠传输。

这种传输方式,虽然可靠但是缺点也比较明显,传输数据的效率非常的低下,好比你现在跟某个人打电话,你说了一句话,只有等到对方回复了你,你才能说下一句,这显然不现实。

为解决这个问题,TCP 引入了滑动窗口,可以一次性向窗口中发送多个数据包并不需要依次等待接受方的确认应答,即使在往返时间较长的情况下,它也不会降低数据传输效率。

那什么是滑动窗口呢?我们以高速路的收费站为例,做一个类比介绍。

上过高速的同学应该都知道,在高速路上有一个入口收费站和一个出口收费站。TCP 也是一样的,除了入口有发送方滑动窗口,出口处也设立有接收方滑动窗口

对于发送方滑动窗口,我们可以把数据包看成车辆,分类它们的状态:

  • 还未进入入口收费站的车辆:对应的是上图Not Sent,Recipient Not Ready to Receive部分,这些属于发送端未发送,同时接收端也未准备接收的数据
  • 已进入收费站但未进入高速路的车辆:对应的是上图Not Sent,Recipient Ready to Receive部分,这些属于发送端未发送,但已经告知接收方的数据,其实已经在窗口中(发送端缓存)了,等待发送。
  • 在高速公路上行驶的车辆:对应的是上图Send But Not Yet Acknowledged部分,这些属于发送端已发送出去,等到接收方接受的数据,属于窗口内的数据。
  • 到达出口收费站的车辆:对应的是上图Sent and Acknowledged部分,这些属于已经发送成功并已经被接受的数据,这些数据已经离开窗口了。

同样,对于接受方滑动窗口,我们也可以把数据包看成车辆,分类它们的状态:

  • 还未到达出口收费站的车辆:状态为Not Received,表示还没有被接收的数据。
  • 到达出口收费站但未完成缴费的车辆:状态为Received Not ACK,表示已经被接受但是还没有回复 ACK
  • 缴完费并离开出口收费站的车辆:状态为Received and ACK,表示已经被接受并回复了 ACK

通过以上的描述,相信大家对滑动窗口已经有了初步的认识,在整个数据传输过程中,光线传输类似于高速公路,TCP 滑动窗口类似于收费站,通过收费站可以做到对车辆进行适当的流量控制,以防止高速公路出现拥堵,滑动窗口也有同样的作用。

4.1、发送方的滑动窗口

下图就是发送方的滑动窗口样例图,根据处理的情况分成四个部分,其中深蓝色方框是发送窗口,紫色方框是可用窗口。

含义解释:

  • #1表示已发送并收到 ACK 确认的数据:1~31 字节
  • #2表示已发送但未收到 ACK 确认的数据:32~45 字节
  • #3表示未发送但总大小在接收方处理范围内:46~51字节
  • #4表示未发送但总大小超过接收方处理范围:52 字节以后

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

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

问题来了,程序是如何精准的控制发送方的窗口数据呢?

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

含义解释:

  • SND.WND:表示发送窗口的大小(大小是由接收方指定的)
  • SND.UNA:是一个绝对指针,它指向的是已发送但未收到确认的第一个字节的序列号,也就是#2的第一个字节
  • SND.NXT:也是一个绝对指针,它指向未发送但可发送范围的第一个字节的序列号,也就是#3的第一个字节
  • 可用窗口大小:是一个相对指针,通过SND.WND - (SND.NXT - SND.UNA)公式计算得来
4.2、接受方的滑动窗口

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

含义解释:

  • #1#2表示已成功接收并确认的数据,等待应用进程读取
  • #3表示未收到数据但可以接收的数据
  • #4表示未收到数据并不可以接收的数据

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

  • RCV.WND:表示接收窗口的大小,它会通告给发送方
  • RCV.NXT:是一个绝对指针,它指向期望从发送方发送来的下一个数据字节的序列号,也就是#3的第一个字节
  • 可接受数据的最大值位置:它可以通过RCV.NXT + RCV.WND计算得出,也就是#4的第一个字节

五、滑动窗口小结

相比传统的发送一个包,然后等待确认应答再发送包的数据传输模型,滑动窗口这种一次性批量发包然后等待确认应答的传输方式,可以显著的提升数据传输效率,整个传输过程可以用如下图来描述。

上图中的 ACK 600 确认应答报文丢失,也不会影响数据传输,因为可以通过下一个确认应答进行确认,只要发送方收到了 ACK 700 确认应答,就表示 700 之前的所有数据接收方都收到了,这种确认应答模式叫累计确认或者累计应答

在上文中,我们提到滑动窗口有一个很关键字的参数,就是窗口大小

通常,窗口的大小是由接收方来决定的,接收端告诉发送端自己还有多少缓冲区可以接收数据,防止发送的数据量过大导致接受方处理不过来,会触发发送方重发机制,从而导致网络流量的无端的浪费。

通过控制窗口大小,可以避免发送方的数据超过接收方的可用窗口,也就是大家常说的流量控制

除此之外,计算机网络都处在一个共享的环境,难免会出现网络拥堵的现象。当网络出现拥堵时,流量控制的手段非常有限。

如果网络出现拥堵时,发送方继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,重传就会导致网络的更拥堵,于是会导致更大的延迟以及更多的丢包,此时可能就会进入恶性循环….

因此,当网络发生拥堵时,TCP 需要主动降低发送的数据量,避免发送方的数据填满整个网络,我们把这一行为称为拥塞控制

关于流量控制和拥塞控制的实现,鉴于文章篇幅过长,我们会在下篇文章中进行详解。

本文整理了一些优秀网友分享的知识,在此感谢作者小林 coding 的《图解 tcp 滑动窗口文章》分享,给予了很大的知识帮助,同时结合自己的理解比较全面的探讨了 TCP 滑动窗口的原理,希望对大家有所帮助。

六、写到最后

不会有人刷到这里还想白嫖吧?点赞对我真的非常重要!在线求赞。加个关注我会非常感激!

此外,本文已整理到技术笔记中,笔记内容还涵盖 Spring、Spring Boot/Cloud、Dubbo、JVM、集合、多线程、JPA、MyBatis、MySQL 等技术知识。需要的小伙伴可以点击 技术笔记 获取!

相关文章:

IO系列(十) -TCP 滑动窗口原理介绍(上)

一、摘要 之前在上分享网络编程知识文章的时候,有网友写下一条留言:“可以写写一篇关于 TCP 滑动窗口原理的文章吗?”。 当时没有立即回复,经过查询多方资料,发现这个 TCP 真的非常非常的复杂,就像一个清…...

IPython 使用技巧整理

IPython 是一个增强的 Python 交互式 shell,提供了许多实用的功能和特性,使得 Python 编程和数据科学工作变得更加便捷和高效。以下是一些 IPython 的使用技巧整理: 1. 自动补全和查询 Tab 补全:在 IPython 中,你可以…...

Python 引入中文py文件

目录 背景 思路 importlib介绍 使用方法 1.导入内置库 importlib.util 2.创建模块规格对象 spec importlib.util.spec_from_file_location("example_module", "example.py") 3.创建模块对象 module importlib.util.module_from_spec(spec) …...

qt 实现模拟实际物体带速度的移动(水平、垂直、斜角度)——————附带完整代码

文章目录 0 效果1 原理1.1 图片旋转1.2 物体按照现实中的实际距离带真实速度移动 2 完整实现2.1 将车辆按钮封装为一个类:2.2 调用方法 3 完整代码参考 0 效果 实现后的效果如下 可以显示属性(继承自QToolButton): 鼠标悬浮显示文字 按钮…...

驱动开发(三):内核层控制硬件层

驱动开发系列文章: 驱动开发(一):驱动代码的基本框架 驱动开发(二):创建字符设备驱动 驱动开发(三):内核层控制硬件层​​​​​​​ ←本文 目录…...

企业邮箱大附件无法上传?无法确认接收状态?这样解决就行

Outlook邮箱作为最常用的邮箱系统,被全世界企业采用作为内部通用沟通方式,但Outlook邮箱却有着明显的使用缺陷,如邮箱大附件上传障碍及附件接收无提示等。 1、企业邮箱大附件无法上传 Outlook企业邮箱大附件的上传上限一般是50M,…...

Kotlin 数据类(Data Class)

Kotlin 数据类(Data Class)是一种特别用于持有数据的类。它们简化了数据类的创建,并提供了一些自动生成的方法。下面详细介绍 Kotlin 数据类的原理和使用方法。 数据类的定义 Kotlin 中的数据类使用 data 关键字定义。例如: da…...

gridview自带编辑功能如何判断用户修改的值的合法性

在使用GridView的编辑功能更新值时,确保输入的值合法性是十分重要的。为了实现这一点,你可以在GridView的RowUpdating事件中加入代码来检查用户输入的值。如果发现输入的值不合法,你可以取消更新操作并向用户显示错误消息。下面是如何实现的步…...

设计模式-结构型-06-桥接模式

1、传统方式解决手机操作问题 现在对不同手机类型的不同品牌实现操作编程(比如:开机、关机、上网,打电话等),如图: UML 类图 问题分析 扩展性问题(类爆炸):如果我们再…...

安泰电压放大器的选型原则是什么

电压放大器是电子电路中常用的一种器件,主要用于放大输入电压信号。在选型电压放大器时,需要考虑以下几个原则。 根据应用需求确定放大倍数。放大倍数是指输出电压与输入电压之间的倍数关系,也称为增益。不同的应用场景对放大倍数的要求不同&…...

方法分享 |公网IP怎么指定非433端口实现https访问

公网IP可以通过指定非443端口实现HTTPS访问。在网络配置中,虽然HTTPS协议默认使用443端口,但没有规定不能在其他端口上实施HTTPS服务。使用非标准端口进行HTTPS通信需要正确配置服务器和SSL证书,并确保客户端能够连接到指定的端口。下面说明如…...

vue实现拖拽元素;vuedraggable拖拽插件

效果图&#xff1a; 中文文档 以下代码可直接复制使用 安装依赖 npm i -S vuedraggable使用 <template><div class"container"><div>使用flex竖轴布局 <br>handle".mover" 可拖拽的class类名 <br>filter".forbid&qu…...

Javascript介绍

Javascript 定义&#xff1a;一门简单的浏览器可解析的语言 作用&#xff1a;与HTML相结合使用&#xff0c;使我们的网页变得更加酷炫 发展史&#xff1a; 1.1992年&#xff0c;Nombase公司开发出来&#xff0c;校验表单&#xff0c;起名c--&#xff0c;后来更名为&#…...

毕业答辩PPT:如何在短时间内高效准备?

提起PPT&#xff0c;大家的第一反应就是痛苦。经常接触PPT的学生党和打工人&#xff0c;光看到这3个字母&#xff0c;就已经开始头痛了&#xff1a; 1、PPT内容框架与文案挑战重重&#xff0c;任务艰巨&#xff0c;耗费大量精力。 2、PPT的排版技能要求高&#xff0c;并非易事…...

树结构与算法-杨辉三角形的两种实现

什么是杨辉三角形 本文旨在讨论普通杨辉三角形的两种实现方式&#xff1a;迭代法和递归法。我们不详细讲解杨辉三角形的数学问题&#xff0c;只研究其代码实现。 杨辉三角形大致如下图&#xff1a; 杨辉三角形的规律 通过对杨辉三角形的图形分析&#xff0c;我们可以看到这几点…...

【机器学习】智能创意工厂:机器学习驱动的AIGC,打造未来内容新生态

&#x1f680;时空传送门 &#x1f50d;机器学习在AIGC中的核心技术&#x1f4d5;深度学习&#x1f388;生成对抗网络&#xff08;GANs&#xff09; &#x1f680;机器学习在AIGC中的具体应用&#x1f340;图像生成与编辑⭐文本生成与对话系统&#x1f320;音频生成与语音合成 …...

Python - 一个恶意脚本

Python - 恶意脚本 使用此脚本或修改前请注意以下几点&#xff1a; 系统资源&#xff1a;大量模拟键盘和鼠标事件可能会占用大量系统资源&#xff0c;会导致其他应用程序运行缓慢或崩溃。 隐私和安全&#xff1a;如果此脚本在未经用户同意的情况下运行&#xff0c;它可能侵犯…...

SFNC —— 采集控制(四)

系列文章目录 SFNC —— 标准特征命名约定&#xff08;一&#xff09; SFNC —— 设备控制&#xff08;二&#xff09; SFNC —— 图像格式控制&#xff08;三&#xff09; SFNC —— 采集控制&#xff08;四&#xff09; 文章目录 系列文章目录5、采集控制&#xff08;Acquisi…...

AUTOSAR学习

文章目录 前言1. 什么是autosar&#xff1f;1.1 AP&#xff08;自适应平台autosar&#xff09;1.2 CP&#xff08;经典平台autosar)1.3 我的疑问 2. 为什么会有autosar3.autosar的架构3.1 CP的架构3.1.1 应用软件层3.1.2 运行时环境3.1.3 基础软件层 3.2 AP的架构 4. 参考资料 …...

区区微服务,何足挂齿?

背景 睿哥前天吩咐我去了解一下微服务&#xff0c;我本来想周末看的&#xff0c;结果周末没带电脑&#xff0c;所以只能周一看了。刚刚我就去慕课网看了相关的视频&#xff0c;然后写一篇文章总结一下。这篇文章算是基础理论版&#xff0c;等我之后进行更多的实践&#xff0c;…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

DiscuzX3.5发帖json api

参考文章&#xff1a;PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下&#xff0c;适配我自己的需求 有一个站点存在多个采集站&#xff0c;我想通过主站拿标题&#xff0c;采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...

内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献

Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译&#xff1a; ### 胃肠道癌症的发病率呈上升趋势&#xff0c;且有年轻化倾向&#xff08;Bray等人&#xff0c;2018&#x…...

Java中HashMap底层原理深度解析:从数据结构到红黑树优化

一、HashMap概述与核心特性 HashMap作为Java集合框架中最常用的数据结构之一&#xff0c;是基于哈希表的Map接口非同步实现。它允许使用null键和null值&#xff08;但只能有一个null键&#xff09;&#xff0c;并且不保证映射顺序的恒久不变。与Hashtable相比&#xff0c;Hash…...