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

【Linux网络】传输层中UDP和TCP协议

文章目录

    • 1、再谈端口号
    • 2、UDP协议
    • 3、TCP协议
      • 3.1 TCP协议段格式
      • 3.2 TCP的三次握手和四次挥手(连接管理机制)
      • 3.3 TCP的滑动窗口
      • 3.4 TCP的流量控制
      • 3.5 拥塞控制
      • 3.6 延迟应答和捎带应答
      • 3.7 面向字节流和粘包问题
      • 3.8 TCP总结

1、再谈端口号

端口号port标识一个主机上的不同应用程序。

比如常见的服务器端口:

  1. HTTP服务器端口号是80
  2. HTTPS服务器端口号是443
  3. FTP服务器端口号是21
  4. SSH服务器端口是22

端口号范围划分

0 - 1023:是一些知名端口号,HTTP,FTP,SSH等这些应用层协议,他们的端口号是固定的。

1024-65532:操作系统动态分配的端口号。客户端程序的端口号就是这个范围里分配的。

通过下面的命令,可以看到所有知名端口号

cat /etc/services

值得注意的是

一个端口只能绑定一个进程,而一个进程可以绑定多个端口。

netstat

netstat是一个用来查看网络状态的重要工具

常用选项

  • n 拒绝显示别名,能显示数字的全部转换成数字
  • l 仅列出在Listen(监听)状态的服务
  • p 显示建立相关链接的程序名
  • t 仅显示tcp相关选项
  • u 仅显示udp相关选项
  • a 显示所有选项,默认不显示LISTEN相关

pidof

在查看服务器进程id时非常方便。

通过进程名,查看进程id

pidof [进程名]

2、UDP协议

UDP协议端格式

img

UDP相关字段

16位的源端口号和目的端口号,保证了数据包的分发。源端口号表明了数据从哪个应用层进程来,到哪个应用层进程去。

16位UDP长度,表示整个数据报(报头+有效载荷)的最大长度。(UDP报文不是流式的,是有边界的,因此可能出现两个报文互相干扰,通过限定数据报大小就能很好解决这个问题)

16位UDP检验和,如果校验和出错,就会直接丢弃。

//报头结构可以理解成一堆字段
struct udp_hdr
{size_t src_port:16size_t dst_port:16size_t udp_len:16size_t udp_check:16
}
//添加报头本质就是在数据前面拷贝一个结构体对象

UDP的封装、解包和分用

UDP报文是定长的,传输层封装就直接在原来的应用层数据上通过指针添加一段结构体对象,另一端在解包时就直接通过定长的8字节找到报文大小,在通过报文减去8字节确定有效载荷数据完成解包。由于报头中有确定的目的端口,因此也能确定特定的应用层协议进程。

UDP的特点

  • 无连接: 知道对方的IP和端口号就直接传输,不要建立连接。
  • 不可靠: 没有确认机制,没有重传机制;如果无法发给对方,也不会有任何错误信息。
  • 面向数据报:不能够灵活的控制读写数据的次数和数量。

无连接和不可靠不能看成是UDP的缺点而是特点,建立连接和保持可靠是需要代价的,在某些场景下恰恰无连接和不可靠才是好的。

其中面向数据报,应用层交给UDP多次的报文,UDP原样发送,既不拆分也不合并。

(比如发送端一次sendto发100个字节,接收端也一定是recvfrom,接收100个字节)

udp缓冲区

  • udp没有真正的发送缓冲区(因为数据简单,并且不用维持连接和可靠性,不用暂存起来),调用sendto会交给内核,由内核将数据传给网络层协议进行后续的传输。
  • udp具有接收缓冲区,因为udp不保证可靠性,所以这个接收缓冲区不能保证收到udp报顺序和发送udp顺序报顺序一样,并且如果缓冲区满了,再次到达的udp数据会被丢弃。

实际上,常用的write这类IO接口,实际上不是将数据写入文件,而是将数据拷贝至系统缓冲区,因为只有系统才了解硬件的情况,因此拷贝到系统缓冲区的数据什么时候发、怎么发都由OS决定。网络中的sendto也是如此。

这类udp的socket既能读也能写,这个概念叫全双工。

可以注意到,16位udp长最大也就64K,很小,如果传输的数据超过64K,就需要应用层手动的分包,多次发送,并在接收端手动拼装。

udp因为其不需要维护其连接和可靠性,在一些链接压力很大并且只需要进行传输数据的场景就非常合适。比如直播

3、TCP协议

tcp传输控制协议的特点是有连接和可靠性,因此谈论tcp协议往往需要讨论其可靠性和效率问题。

3.1 TCP协议段格式

img
  • 16位源端口号和16位目的端口号和UDP一样,源端口号表明了数据从哪个应用层软件来,到哪个应用层软件去。
  • 4为首部长度表示TCP报头有多少个4字节。因此如果显示是0101,那么报头大小为5*4 = 20字节。因此报头的范围为20-60.

TCP的封装、解包和分用:

封装:TCP的数据报大小是动态的,其报头也是通过字段组成。因此在封装的时候,也是在应用层数据的基础上添加一个结构体对象。

解包:在解包的时候通过4位首部长度*4减去20字节标准报头就可以确定还有多少剩余报头,提取完报头剩下的就是有效载荷。对于有效载荷的边界问题,后面再详细讨论。

分用:分用一样是通过目的端口号确定特定的应用层协议进程。

TCP可靠性问题:

  1. 什么是不可靠? 丢包、乱序、数据包检验失败
  2. 怎么确认一个报文是丢了还是没有丢? 如果收到应答就确认没丢,没有就不确定。

TCP不提供有效载荷大小的字段,而是采用一种确认应对机制,确保数据传输可靠。

那么如果面对多种请求,如何确定哪些是确认收到的呢?

img

对于发送的多个信息,只有收到的信息是和发送有对应关系的,才能确定发出去的数据是可靠的。

因此,TCP报头中有两个重要的字段:32位序号和32位确认序号。

其中序号标识传输的当前报文,确认序号代表确认接收到了当前所有之前序号的报文。因此序号和确认序号保证了两端通信数据的可靠性。

那为什么一个报文中要同时存在序号和确认序号两个字段呢?

因为tcp是全双工的,当server在确认回应的同时也可能向Client发送数据,因此就需要一个报文设置两份序号。

为了保证序号安全,序号生成不能有规律,即序号生成是随机生成的,并且与报文有关。溢出也会有方法进行回绕。

TCP发送缓冲区和接收缓冲区的关系

tcp协议传输需要保证其可靠性,因此在发送的时候需要有发送缓冲区(比如为了超时重传进行备份数据),另一端也需要有接收缓冲区暂存还未被应用层提取的数据。

img

实际上用户层上会有自己定义的缓冲区,并且IO类函数本质都是拷贝函数,将用户数据拷贝到内核,再由内核拷贝给用户,因为OS比用户更清楚底层的情况。

因此,数据怎么发,出错了怎么办,要不要添加提高效率的策略,这些都是由OS中TCP自主决定的,所以TCP对数据是具有传输和控制能力的,也就被称为传输控制协议。

其实在文件操作中,虽然用户拷贝到内核缓冲区的数据是由OS决定何时何样写到文件中,但也提供一些接口如fsync刷新缓冲区接口给用户带来确定性。网络更需要这样,不然在用户发送后,OS经过一些决定后才算发送成功,那么效率就太慢了。

TCP协议中有自己的发送缓冲区和接收缓冲区,因此一端在接收数据的时候也能向对方发数据。全双工的通信特点也因此。

16位窗口大小的应用

img

如果当client向server发消息速度过快,导致server缓冲区满了,那么后续的数据接收不了该怎么办呢?

让client重传这个做法显然是不太行的,因为client传递的数据是需要成本的,如果在到达后才知道server接收不了数据,这很影响效率。

有没有一种能提前知道对方接受能力的策略?报头中的窗口大小字段很好的解决。

client给server发消息后,server的应答报文中是会有窗口大小字段的。这个窗口大小就是接收缓冲区的剩余接收容量。

双方都可以通过传输报文的同时携带自身的窗口大小,让对方知道自己接收缓冲区的剩余接收容量,这一双向的行为也称流量控制。

6位标志位

两端进行TCP协议的整个通信过程中,有相互建立链接的过程,有通信的过程,有断开链接的过程。在这些过程中,发送的报文也有很多的类别,需要用不同逻辑区分这些报文。

img
  • SYN:请求建立连接,把携带SYN标识的称为同步报文段。只要报文是建立链接请求,标识为1,证明这一次是建立连接的请求。
  • FIN:通知对方,本端要关闭了。携带这种标识的称为结束报文段
  • ACK:确认标记位,标识该报文是对历史报文的确认。(发送的确认报文不仅仅可以是确认,也可以边确认边发消息)
  • PSH:提示接收端应用立刻从TCP接收缓冲区内把数据读走。(可以理解为催促报文,一种就绪数据通知策略)
  • URG:紧急指针标记位。TCP为了保证其数据可靠性,通过在缓冲区将序号进行排序,让发报文和收报文的顺序是一样的。但如果有一些数据优先级更高,但序号较晚,因此有优先被要求的需求。通过URG标记,让报文是优先被读的类型。(之后通过16位紧急指针在数据中获得特定的偏移量位置的数据,并且该数据只有1个字节。在一些极端情况下,常用于查看机器的状态)
  • RST:对方要求重新建立连接; 我们把携带RST标识的称为复位报文段。(如果Client回应ACK后Server没有收到,此时Client以为建立成功就直接开始通信,而Server看到没有建立链接就发信息,于是发一个RST的报文,要求让对方重新建立链接。)

3.2 TCP的三次握手和四次挥手(连接管理机制)

img

TCP的三次握手

tcp是面向连接的,如果多个客户端与TCP服务器建立链接,OS就需要管理这些链接,就需要管理维护这些链接的结构体。(花时间、花空间)

为什么是三次握手?

img
  • 一次行不行?SYN一次不一定成功,并且很容易收到攻击(构造假的SYN请求,引发SYN洪水,使得服务端一直建立维护链接的结构体,不断消耗其资源)
  • 两次行不行?SYN+SYN+ACK,server还是认为一次SYN就成功了,其实和一次是一样的。Client只要忽略你发的请求,就还是可以和一次的SYN攻击一样的。
  • 三次?三次让客户端先建立维护链接的结构体,再回复给server。这样客户端就要和服务端受到同等代价,而服务器资源肯定是要比单主机资源多的。同时三次的ACK失败不影响server,而是影响client。(奇数次链接成本能够嫁接到客户端)

三次握手也用最小成本验证了全双工。

TCP的四次挥手

img

TCP是全双工的,通信双方地位是共有的,你关闭对应链接,我也要关闭对应链接。

客户端主动关闭连接,向服务端发送FIN结束报文,服务端返回确认报文段进入CLOSE_WAIT,处理完之前数据就close关闭连接,向客户端发送FIN结束报文,等待最后一个ACK到来后,就彻底关闭连接,客户端等待后,进入CLOSED。

进入CLOSE_WAIT状态的服务器此时因为没有close对应socket而占用资源。因此可能会有内存泄漏危险。

因为TCP是全双工的,在特殊情况下Server方的ACK和FIN可能会以一个报文的形式发送。

一个现象:为什么服务器关闭,客户端再关闭,客户端还要进入TIME_WAIT状态?

因为最后的ACK回应报文可能是丢失的,如果Client完成四次挥手直接进入CLOSED状态,可能Server还没有完成四次挥手最后以异常情况关闭链接,这有问题。因此,Client收到FIN后向Server发送ACK,如果之后没有发生Server因为超时重传FIN的情况,Client就正常退出。

那么这个TIME_WAIT等待的时长是多少呢?

Client->Server,Server->Client一来一回时长是要浮动的,其中最长的被称为TCP最大生存时间MSL,而TIME_WAIT等待时间如果设定为2*MSL,就能保证完成一次一来一回。

不过一般MSL都是被系统设置好了,这是为了保证两个传输方向上不收到尚未被接收或迟到的报文段。

[yzh@VM-4-8-centos ~]$ cat /proc/sys/net/ipv4/tcp_fin_timeout 
60

在极端情况下

TIME_WAIT意义从宏观上来看,Client可能在传Data同时传了FIN,当FIN先到达时,TIME_WAIT就能很好保证剩余数据也能被处理。

不过在一些场景下,需要服务器及时启动,让其它不同IP或端口的客户端能够bind成功随后链接。

//通过setsockopt设置的socket,level一般设置为SOL_SOCKET代表socket层,选项optname有SO_REUSEADDR和SO_REUSEPORT,分别代表能以不同的IP和端口进行绑定链接。opt代表设置新值的缓冲区。
#include <sys/socket.h>
int setsockopt(int socket, int level, int option_name, const void *option_value, socklen_t option_len);int opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

3.3 TCP的滑动窗口

TCP的Listen和Accept

#include <sys/socket.h>
//socket是套接字。
//如果backlog上层不进行accept,底层建立好的链接数就是有上限的,上限是backlog+1。
int listen(int socket, int backlog);
int accept(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len);
img

在TCP三次握手之前,listen是一个等待链接的接口,在调用accept之前,建立链接后,会在底层建立一个链接好的队列。里面都是全链接(ESTABLISHED)状态的结构体。此时已经建立好链接。(在链接数超过backlog+1后,再次建立的链接就会处于SYN_RCVD半链接状态)

accept不参与三次握手,但底层会维护一个链接队列,accept将底层链接拿到上层,给用户看到。

重点是为什么要有这个队列呢?

1、为什么要排队?

可以让我们Server在有闲置的情况下,从底层拿去链接,进行链接处理。

2、为什么不能太长?

太长影响客户体验,太长过于占用资源,反而可能导致服务器效率低下。(与其增加更多的排队资源,不如腾出更多的资源给客户使用)

TCP的确认应答机制

img

之前的确认应答机制,主机间的通信发一次给一次应答,整个过程是串型的。这种做法效率很低。TCP采用它的思想,但不按照这样做。

img

通过并行的确认应答机制,接收一堆,响应一堆。TCP发送真正采用的是这种策略。

滑动窗口和缓冲区

img

发送出去的数据,在没有得到回应的情况下,必须被保留在发送缓冲区以便支持超时重传。

img

在发送缓冲区中,已经发送,但没有得到响应的区域,就是可能会出现超时重传的数据的区域。

img

它的整个区域大小也就决定了当前最多能发多少的数据给接收端,能发多少也就取决于接收端有多少的吞吐量,而衡量这一标准采用的就是接收端的16位窗口大小字段。在发送数据的过程中,这个区域的大小随着接收端的窗口大小而变化,因此形象称之为滑动窗口。

上图中,假设开始滑动窗口位4KB,同时也对应接收端接收缓冲区为4KB,当其中4KB数据全部传输过去,但接收端的用户进程一点都不取。这时接收缓冲区的剩余容量就是0,因此滑动窗口大小也就为0。(同时滑动窗口的移动不可能向左,并且不用担心越界问题,因为在实现角度上可以通过一个缓冲区数组的下标进行取模调整,因为滑动窗口之前的数据都是无用数据了。)

滑动窗口与超时重传策略

img

假设接收端接收缓冲区接收能力一直不变,当传输序号为1001~2000的报文,当收到2001的确认序号,滑动窗口起始就移到2001,代表之前数据发送成功。

那么在传多个报文的时候,中间报文丢失了怎么办?

情况1:数据包完整,ACK丢了。

img

如上图,假设同时发送4种报文,其中只收到了确认报文4001,其它的确认报文都丢失怎么办呢?

只要确认序号收到4001,那么就代表4001前的都收到,前面丢的都可以忽略,start_index就可以直接到4001。

情况2:数据包丢了

img

数据一直从1 ~ 1000发到6001 ~ 7000,接收端的接收缓冲区里除了1001 ~ 2000的数据包,其它的都收到了。因此返回确认报文时,确认序号总是1001,当发送端收到3个同样的确认应答时就会知道对应数据包丢失了,进行重发。之后如果接收端收到了1001 ~ 2000的数据包,就会返回确认序号为7001的报文,代表之前序号的报文都收到了。(对应滑动窗口start_index就到了7001)

这种机制被称为 “高速重发控制”(也叫 “快重传”)

综上:滑动窗口能在一定上提高传输的效率,同时也能很好的解决TCP的丢包问题。

3.4 TCP的流量控制

在前面介绍窗口大小字段的时候,为了让发送端知道接收端的剩余接收容量,在接收端发送报文给发送端的时候会附带一个窗口大小字段,代表当前还能接受多少的数据量。因为TCP是全双工的,双方都可以这么做。

因此TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制

如果接收端缓冲区满了,就会将窗口置为0;这时发送方不再发送数据,但是发送方会定期发送一个窗口探测数据段(如果过了重发超时的时间还没收到窗口更新的通知,就会发一个窗口探测的包),再由接收端把窗口大小告诉发送端。(但这个返回的窗口通知是可能会丢失的,因此发送端主机会时不时发送窗口探测包。)

不过窗口大小是16位的,最大也就64K,那么数据超过这个怎么办?在TCP首部中选项中有对应的扩大因子,会将实际窗口大小字段左移。

3.5 拥塞控制

在之前,我们考虑了主机之间的数据可靠问题、效率问题、流量控制问题,但是这些都是主机和主机之间的。网络通信还必须考虑主机和网络之间的问题。因为网络上有很多的计算机,可能当前网络状态已经很拥堵,如果在不清楚网络的状态下,贸然发送大量数据,是很有可能引起雪上加霜的。

当发送方发送1K个报文,在接收端接收时发现少了2、3个报文。此时可能是发送端或接收端问题,这没事,大不了就超时重传一下。

如果发送方发送1K个报文,在接收端接收时发现少了大量的报文,此时就不应该是发送端接收端的问题,因为它们之间有策略保证了数据的可靠性问题。此时大概率就是网络的问题了。

因为网络拥塞问题出现大量的丢包,那能重传吗?

接入网络的主机是很多的,如果网络出问题,这么多的主机出现丢包如果超时重传的话,那么一定会有一定量的主机在同一时间段向网络发送数据,造成了大量的数据向网络里塞,网络压力本来就很大,因此这种方式不行。

那解决方案?拥塞控制!

TCP引入慢启动机制,识别到网络拥塞,先发少量的数据探探路,摸清当前的网络拥堵状态,再按照多大的速度传输数据。

在这里插入图片描述

拥塞窗口,发送的数据在这个窗口数据量内不会发生阻塞,超过这个量可能会导致网络拥塞问题。

在之前,一次向目标主机发送数据的量是对方窗口大小,现在考虑网络,一次向目标主机发送数据最大的量就应该是对方窗口大小和网络拥塞窗口的较小值。

在发生开始的时候,定义拥塞窗口大小为1,每次收到一个ACK应答,阻塞窗口以2倍增长。这种”慢启动“在初始时慢,但是增长速度很快,这也是为了想尽快把数据传给对方。当拥塞窗口超过某个阈值的时候,不再按照指数级方式增长,而是按照线性增长。如果再次遇到网络拥塞,就会再次降低拥塞窗口进行慢启动。

综上:拥塞控制是为了TCP协议尽快把数据传输给对方,但又要避免给网络造成拥塞的折中方案。

3.6 延迟应答和捎带应答

延迟应答

如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小,因为接收发上层用户还没从接收缓冲区里取走数据,窗口大小就被返回了。

假设接收缓冲区的大小是1M,一次收到了500K的数据;如果立刻应答,返回的窗口就是500K。如果等待一段时间让上层用户将缓冲区中的500K数据取走,再返回的窗口就又是1M。

值得注意的是:窗口越大,网络的吞吐量就越大,传输效率就越高,我们目标是保证在网络不拥塞的前提下提高传输效率。

那么这个等待时间如何把握呢?毕竟等待是为了更好的提高传输效率,如果等待过长就得不偿失了。

  • 数据限制:每隔N个包就应答一次。(一般N=2)(更多)
  • 时间限制:超过最大延迟时间就应答一次。(一般200ms)

捎带应答

稍等应答很简单,在之前认识TCP两端进行通信的时候,大多数是”一发一收“的,在ACK的时候可以不仅是发送确认,同时也可以发送我想给你发的有效信息。

3.7 面向字节流和粘包问题

创建一个TCP的socket, 会同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区;

建立连接的双端,有两套缓冲区,彼此可以互相读写,因此构成了全双工。

在写入和读取缓冲区字节的时候,可以任意控制其数量以及次数。

TCP是面向字节流的,接收和发送不关系任何数据格式,但是应用层要正确使用这里的数据,是需要有特定数据格式的(在应用层就需要自己定制协议)。如果数据处理直接从流氏空间中以特定字节读取的话,就很可能读到多个数据包的内容,这就是TCP粘包问题。(就是蒸包子时还没分开直接拿的时候,可能会拿到其它包子的部分)

如果明确报文和报文的边界?

1、通过特定的标识符将其分开。(比如http中的空行、\r\n)

2、可以在报头位置,约定一个包总长度的字段。(比如http属性中的content-length)

UDP协议没有”粘包问题“,因为其报头中有明确的报文长度字段,这保证了其报文的边界。

3.8 TCP总结

TCP的复杂就是为了保证其可靠性以及尽可能提高性能。

可靠性:

  • 校验和
  • 序列号(确保发送和接收的顺序性)
  • 确认应答(通过序号和确认序号)
  • 超时重发
  • 连接管理(三次握手,四次挥手)
  • 流量控制(通过窗口大小,决定数据能被接收的量,同时也决定了发送方的速度)
  • 拥塞控制(在保证网络不拥塞的情况下,维持TCP最大的传输速度)

提高性能:

  • 滑动窗口( 让数据并行可靠的向对方发送)
  • 快速重传(发送丢包时,发送方通过边传数据边识别多次收到相同确定序号报文的快重传策略)
  • 延迟应答
  • 捎带应答

相关文章:

【Linux网络】传输层中UDP和TCP协议

文章目录 1、再谈端口号2、UDP协议3、TCP协议3.1 TCP协议段格式3.2 TCP的三次握手和四次挥手&#xff08;连接管理机制&#xff09;3.3 TCP的滑动窗口3.4 TCP的流量控制3.5 拥塞控制3.6 延迟应答和捎带应答3.7 面向字节流和粘包问题3.8 TCP总结 1、再谈端口号 端口号port标识一…...

工具︱ Web3加密浏览器Brave有什么特别之处?

使用浏览器来上网访问和获取各种信息和资源已经成为传统互联网民的普遍活动&#xff0c;下一代互联网协议Web3的核心特点是去中心化&#xff0c;即不依赖于中心化的服务器和数据中心&#xff0c;而是通过分布式的网络节点来实现数据存储和传输。 浏览器承载着信息网络与用户需求…...

绝对不能错过这份沃尔玛实用插件工具大全

龙哥最近发现很多跨境卖家都比较少运营沃尔玛这个平台。沃尔玛除了是世界500强之外&#xff0c;它的线上商城也弄得很好。它的电商平台主要是售卖自营的&#xff0c;然后你也可以入驻来卖自己的产品&#xff0c;就像是我们国内的京东一样。今天龙哥就给大家分享一些沃尔玛专用插…...

【Java】字符串模板拼接的方法

引 在Java中&#xff0c;构建字符串是非常常见的操作。在很多时候&#xff0c;我们都需要使用变量或输入来定制一个文本输出&#xff0c;例如打印日志、生成HTML代码或构建错误消息。而当需要进行字符串连接时&#xff0c;字符串模板是一种常用的方法。在本篇博客中&#xff0…...

Vue3项目中使用ECharts图表并实现自适应效果

文章目录 一、Vue3项目安装ECharts二、引入、使用ECharts1.创建图表组件&#xff0c;并在父组件中引入使用2.引入ECharts3.ECharts图表自适应 总结 一、Vue3项目安装ECharts 在项目中输入如下代码&#xff1a; npm install echarts --save安装完成可以在package.json中看到&a…...

快速跑通环信IM Android Demo

1、以Android 4.0.0 Demo为例 https://www.easemob.com/download/demo &#xff08;下载别的版本的demo 可以修改版本号直接下载就就可以&#xff09; https://downloadsdk.easemob.com/downloads/easemob-sdk-4.0.0.zip 运行时遇到以下报错在项目build.gradle中添加运行时遇…...

leetcode解题思路分析(一百三十九)1190 - 1196 题

反转每对括号间的子串 给出一个字符串 s&#xff08;仅含有小写英文字母和括号&#xff09;。请你按照从括号内到外的顺序&#xff0c;逐层反转每对匹配括号中的字符串&#xff0c;并返回最终的结果。注意&#xff0c;您的结果中 不应 包含任何括号。 可以简单的用栈保存当前层…...

PHP+vue基于web的小区物业管理管理系统1995a

小区物业管理系统主要是对小区物业以及居民信息进行管理&#xff0c;方便用户使用该资源的一种有效手段。能有效地对物业以及用户信息进行管理并为广大用户服务是该管理系统的基本要求&#xff0c;同时用户也可以及时了解最新的物业信息&#xff0c;方便地查询相关物业情况。基…...

区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测

区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测 目录 区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测效果一览基本介绍模型描述程序设计参考资料 效果一览 基本介绍 区间预测 | MATLAB实现QRCNN卷积神经网络分位数回归时间序列区间预测…...

【AI 导航网站】为了更好的收集 AI 资源,我开发了一个 AI 导航网站

AI 导航网站 目前 AI 应用正呈迸发式增长&#xff0c;然而一个人获取资源的途径有限&#xff0c;对于目前存在的AI工具不能很好的收集总结&#xff0c;所以基于此&#xff0c;我开发了这个一个AI导航网站&#xff0c;希望通过它&#xff0c;收集出目前存在的热门的AI应用&…...

谈谈HMI 的自动化生成技术

人机界面&#xff08;HMI&#xff09;是自动化领域不可或缺重要组成部分。尽管人机界面系统的设计看上去并没有太大的技术门槛&#xff0c;但是设计一个HMI系统的工作量是巨大的。如果你没有足够的耐心便完成不了一个通用的HMI系统。构建UI控件库是一个似乎永远完不成的事情&am…...

docker安装elasticsearch

使用docker部署 部署elasticsearch # 拉取镜像 docker pull elasticsearch# 创建容器 docker run --name es -p 9200:9200 \-p 9300:9300 \-e "discovery.typesingle-node" \-e ES_JAVA_OPTS"-Xms64m -Xmx128m" \-v /home/es/conf/elasticsearch.yml:/…...

Docker:使用dockerFile创建镜像(war包和jar包)

1、使用war包打镜像 &#xff08;1&#xff09;在war的当前路径下&#xff0c;新建一个文件——Dockerfile &#xff08;2&#xff09;编辑Dockerfile文件 vim Dockerfile Dockerfile文件内容&#xff1a; FROM java:8 # 选择项目中要求的版本 MAINTAINER ylb …...

2.基础篇

目录 一、描述软件测试的生命周期&#xff08;软件测试的流程&#xff09; 二、如何描述一个bug 三、bug的级别&#xff08;粗略划分&#xff09; 四、bug的生命周期 五、因为一个bug和开发人员产生争执怎么办 六、如何设置弱网&#xff1f; 一、描述软件测试的生命周期&a…...

取代你的可能不是AI,而是比你更会使用AI的人

1、背景 从开始了解AI到现在已经1个月了&#xff0c;最明显的就是&#xff0c;产品层出不穷&#xff0c;以前只有技术人员才关系AI&#xff0c;现在各行各业都在关系AI&#xff0c;都希望通过它提高生产力和创造力&#xff1b; 在当今大数据和人工智能时代&#xff0c;职场和企…...

NECCS|全国大学生英语竞赛C类|词汇和语法|语法题|时态 非谓语动词 |19:00~20:15|完形填空·词性转化

14:35&#xff5e;14:45 15:45&#xff5e;16:2019:00&#xff5e;20:15 http://t.csdn.cn/XbsUy 目录 &#xff08;一&#xff09;时态 7. 将来进行时 8. 过去将来进行时 9. 现在完成时 10. 过去完成时​编辑 11. 将来完成时 12. 现在完成时 13. 过去完成进行时 &#xff08;…...

【高等数学笔记】Stolz定理

文章目录 Stolz定理 ∗ ∞ \cfrac{*}{\infty} ∞∗​型 0 0 \cfrac{0}{0} 00​型 例子1. 算术平均数的极限2. Stolz定理可以被理解为“数列的洛必达法则”&#xff0c;它揭示了两个数列之比的极限和相邻两项之差的比的极限的关系。 Stolz定理 ∗ ∞ \cfrac{*}{\infty} ∞∗​型…...

【24】核心易中期刊推荐——图像处理研究大数据及智能处理研究

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…...

Codeforces Round 870 (Div. 2)【A、B、C、D】

文章目录 A. Trust Nobody(暴力)B. Lunatic Never Content(数学)C. Dreaming of Freedom(数学、暴力)D. Running Miles(前缀、后缀) 传送门 A. Trust Nobody(暴力) 题意&#xff1a;给出n个人的陈述&#xff0c;每个人陈述至少有ai个人说谎&#xff0c;让你求出可能是说谎人数…...

BetaFlight统一硬件AOCODARC H7DUAL配置文件讨论

BetaFlight统一硬件AOCODARC H7DUAL配置文件讨论 1. 源由2. Review配置3. 分析整理3.1 生产商信息3.2 磁力计3.3 气压计3.4 陀螺仪3.5 串口RxTx3.6 板载Flash3.7 模拟OSD MAX74563.8 PPM接收机3.9 伺服器3.10 LED灯带3.11 蜂鸣器3.12 电机 X83.13 ADC(电压/电流/RSSI信号强度/空…...

力扣题库刷题笔记682-棒球比赛

1、题目如下&#xff1a; 2、个人Python代码实现如下&#xff1a; 代码如下&#xff1a; class Solution: def calPoints(self, operations: List[str]) -> int: i 0 #用于遍历元素的下标 while i < len(operations): …...

SpringCloud------Eureka修改实例显示信息、服务发现Discovery、自我保护(六)

SpringCloud------Eureka修改实例显示信息、服务发现Discovery、自我保护&#xff08;六&#xff09; 1.actuator微服务信息完善 2.服务发现Discovery 3.Eureka自我保护 actuator微服务信息完善 web和actuator依赖用于图形化监控 1.主机名称&#xff1a;服务名称修改 新增…...

Java 远程debug,IDEA 远程 Debug 调试

有时候我们需要进行远程的debug&#xff0c;本文研究如何进行远程debug&#xff0c;以及使用 IDEA 远程debug的过程中的细节。看完可以解决你的一些疑惑。 配置 远程debug的服务&#xff0c;以SpringBoot微服务为例。 首先&#xff0c;启动SpringBoot需要加上特定的参数。 …...

将webrtc的音频模式改为共享模式

修改音频设备模式:打开文件modules/audio_device/include/audio_device.h,将AudioDeviceModule::kPlatformDefaultAudioProcessing为true改为false。这将禁用默认的音频处理,使得可以修改音频设备模式。 修改音频设备模式的初始化:打开文件modules/audio_device/audio_dev…...

电脑cpu占用率高?怎么办?1分钟快速解决!

案例&#xff1a;电脑cup过高怎么办&#xff1f; 【我的电脑运行缓慢&#xff0c;导致我学习和工作的效率很低。刚刚查看了一下电脑&#xff0c;发现它的cpu占用率很高。有没有小伙伴知道如何解决此电脑cpu过高的问题&#xff1f;】 电脑是我们生活中不可缺少的工具&#xff…...

使用JPA自动生成代码(轻松上手看了就会版)

目录 背景&#xff1a;方案概念&#xff1a;JPA 的主要作用 jpa简单使用&#xff08;Springboot项目&#xff09;jpa进阶使用总结 背景&#xff1a; 项目需要自动生成sql代码&#xff0c;不需要写sql语句&#xff0c;能够自动进行查询&#xff0c;我想到了JPA。 方案 概念&a…...

jdk动态代理

jdk动态代理:基于反射动态生成代理对象 pwp动态代理的步骤比较复杂&#xff0c;无需特别深入的理解&#xff0c;在jdk中固定的步骤&#xff0c;只需要知道这些步骤即可&#xff0c;不必钻牛角尖 动态代理涉及到的三个反射包类 InvocationHandlerMethodProxy 1. InvocationHand…...

备忘录模式

备忘录模式 备忘录模式定义使用场景1、撤销操作&#xff1a;2、游戏进度保存&#xff1a;3、定时器&#xff1a;4、浏览器历史记录&#xff1a;5、购物车状态保存&#xff1a;6、场景总结 角色定义Originator 发起人角色:Memento 备忘录角色:Caretaker 备忘灵管理员角色:需求背…...

问题解决:跨域访问错误

今天做前端页面渲染的时候遇到一个问题, 因为我使用的wsl开发,windows直接访问不了wsl中的文件,还要改其他配置没成功,索性就不改了,粘贴在桌面上用浏览器打开调试 然后所有使用apifox通过测试的路径全部报错 Ensure CORS response header values are validA cross-origin reso…...

程序员应该怎么自学才能入门 ?我来聊聊自己的经历

当你想成为一名程序员&#xff0c;如何自学入门是一个非常重要的问题。在这里我分享一下我的经验&#xff0c;希望能对你有所帮助。 首先&#xff0c;为了制定好你的学习路线&#xff0c;你可以在网上的培训机构网站找到一张基础路线图。这张路线图必须是跟行业对标的&#xf…...