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

news2024/11/18 1:44:08

文章目录

    • 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:16
	size_t dst_port:16
	size_t udp_len:16
	size_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最大的传输速度)

提高性能:

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

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

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

相关文章

动态规划算法——40道leetcode实例入门到熟练

目录 t0.解题五部曲1.基础入门题目1.509. 斐波那契数2.70. 爬楼梯3.746. 使用最小花费爬楼梯4.62. 不同路径5.63. 不同路径 II6.343. 整数拆分7.96. 不同的二叉搜索树 2.背包问题1.01背包&#xff08;二维数组实现&#xff09;2.01背包&#xff08;滚动数组实现&#xff09;1.4…

OpenPCDet系列 | 4.数据集数据加载流程

文章目录 数据加载流程0. create_kitti_infos1. __getitem__函数2. prepare_data函数3. collate_batch函数数据加载流程 这里记录一下具体用到的那些数据形式,整个kitti数据集的处理框架图如下所示: 在数据集处理到获取一个batch数据的整个流程的入口如下: # 开始迭代每…

01-微服务部署2023系列-centos安装nginx和jdk教程

centos安装nginx和jdk教程 一、centos安装nginx 0、前提:安装依赖 yum -y install gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre pcre-devel 1、压缩包 下载nginx 选择Stable version: http://nginx.org/en/download.html 上传压缩包到…

yolov3核心网络模型

1. 改进概述 yolov3主要围绕核心网络Darknet优化进行。 yolov3的速度和map值比之前的算法优秀。 改进包含&#xff1a;网络结构、特征融合、先验框&#xff1a; V1 2, V25,V39、Softmax等。 softmax 2. 多scale方法改进与特征融合 3. 经典变换方法 预测中目标时&#xff0c…

Nacos配置管理、Fegin远程调用、Gateway服务网关

1.Nacos配置管理 Nacos除了可以做注册中心&#xff0c;同样可以做配置管理来使用。 1.1.统一配置管理 当微服务部署的实例越来越多&#xff0c;达到数十、数百时&#xff0c;逐个修改微服务配置就会让人抓狂&#xff0c;而且很容易出错。我们需要一种统一配置管理方案&#xf…

Spring-IOC

IOC概念和原理 什么是IOC 控制反转&#xff0c;为了将系统的耦合度降低&#xff0c;把对象的创建和对象直接的调用过程权限交给Spring进行管理。 IOC底层原理 XML解析 ​ 通过Java代码解析XML配置文件或者注解得到对应的类的全路径&#xff0c;获取对应的Class类 Class clazz …

Django框架之模型查询介绍及示例

本篇文章所使用模型查询都在《Django框架之模型自定义管理器》基础上讲解查询和使用示例&#xff0c;通过看前篇可以有助于理解内容。 概述 查询集&#xff1a;从数据库获取的对象集合 查询集可以有多个过滤器 过滤器就是一个函数&#xff0c;根据所给的参数限制查询集结果 …

【Vue学习笔记5】Vue3中的响应式:ref和reactive、watchEffect和watch

所谓响应式就是界面和数据同步&#xff0c;能实现实时更新。 Vue 中用过三种响应式解决方案&#xff0c;分别是 defineProperty、Proxy 和 value setter。Vue 2 使用的方案是 defineProperty API。Vue3中使用的方案是Proxy和value setter。 1. ref和reactive vue3中实现响应…

基于docker部署ELK实战- ELK文章1

选择版本为elasticsearch:7.17.9&#xff0c;kibana:7.17.9&#xff0c;logstash:7.17.9 版本一定要一致 docker hub地址&#xff1a;https://hub.docker.com elk相关文档&#xff1a;https://www.elastic.co/guide/en/kibana/7.17 一、部署单点es 1.创建网络 因为我们还需要…

iframe嵌套grafana (前端视角)

1、grafana 启动方式 ①.grafana目录鉴赏。咱们就是直接拿到配置好的grafana。咱们暂时不涉及配置数据啥。 ①.双击grafana-server.exe &#xff0c;会出现黑色命令框。 ②.在浏览器中访问 http://localhost:3000 此时就可以看到配置好的grafana 2.前端嵌入 ①.html <…

消息队列中间件 - Docker安装RabbitMQ、AMQP协议、和主要角色

概述 不管是微服务还是分布式的系统架构中&#xff0c;消息队列中间件都是不可缺少的一个重要环节&#xff0c;主流的消息队列中间件有RabbitMQ、RocketMQ等等&#xff0c;从这篇开始详细介绍以RabbitMQ为代表的消息队列中间件。 AMQP协议 AMQP协议是一个提供统一消息服务的应…

图像处理:基于cv2.inpaint()图像修补

前言 今天我们将学习如何通过一种“修复”的方法消除旧照片中的小噪音&#xff0c;笔画等。当然&#xff0c;经过我的测试你也可以将其用于削弱混杂了其他的颜色的图像。 实验背景 大多数人家都会有一些旧的的旧化照片&#xff0c;上面有黑点&#xff0c;一些笔触等。你是否…

从零实现深度学习框架——常见学习率调整策略原理与实现

引言 本着“凡我不能创造的&#xff0c;我就不能理解”的思想&#xff0c;本系列文章会基于纯Python以及NumPy从零创建自己的深度学习框架&#xff0c;该框架类似PyTorch能实现自动求导。 &#x1f4a1;系列文章完整目录&#xff1a; &#x1f449;点此&#x1f448; 要深入理解…

day24_多线程

今日内容 零、 复习昨日 一、作业 二、线程安全的集合 三、死锁 四、线程通信 五、生产者消费者 六、线程池 零、 复习昨日 见晨考 一、作业 售卖后车票 见代码二、线程安全的类[了解] StringBuffer是线程安全的,是因为每个方法都加上synchronized,即都是同步方法 StringBuil…

【前端】前后端分离ruoyi-vue初步学习

1.了解vue基础知识。 Vue.js - 渐进式 JavaScript 框架 | Vue.js (vuejs.org) 2.将ruoyi-vue项目拉下来&#xff0c;并成功运行。 开源项目网址&#xff1a;RuoYi 若依官方网站 |后台管理系统|权限管理系统|快速开发框架|企业管理系统|开源框架|微服务框架|前后端分离框架|…

《Netty》从零开始学netty源码(五十四)之PoolThreadLocalCache

PoolThreadLocalCache 前面讲到PoolThreadCache&#xff0c;它为线程提供内存缓存&#xff0c;当线程需要分配内存时可快速从其中获取&#xff0c;在Netty中用PoolThreadLocalCache来管理PoolThreadCache&#xff0c;它的数据结构如下&#xff1a; PoolThreadLocalCache相当…

【网络】UDP网络服务器简单模拟实现

【网络】UDP网络服务器简单模拟实现 文章目录 makefile服务端udpServerudpServer.ccudpServer.hpp初始化启动测试 客户端udpClientudpClient.ccudpClient.hpp初始化启动 整体代码 UDP的封装: UDP网络服务器模拟实现&#xff1a;主要分为makefile文件进行编译 UDP客户端&#xf…

Java开发 - 不知道算不算详细的分布式事务详解

前言 前日对JUC进行了一个深度总结&#xff0c;不过现在博主能记得的也不多了&#xff0c;只是这东西&#xff0c;不是看几遍写几遍就能完全记住的&#xff0c;功夫在平时&#xff0c;很多知识点都需要反复的看&#xff0c;不光要看&#xff0c;还要用&#xff0c;这样才能了解…

在CentOS上安装Jenkins并配置Docker

文章目录 步骤1 - 安装Java 11步骤2 - 安装Jenkins步骤3 - 安装Docker步骤4 - 配置Docker Cloud步骤 5 - 验证步骤 6 - 可能会遇到的问题 在本教程中&#xff0c;我们将展示如何在CentOS上安装Jenkins和Docker&#xff0c;并将它们配置在同一台机器上&#xff0c;使Jenkins能够…

《花雕学AI》WeTab+ChatGPT:让浏览器变成你的智能助手

引言&#xff1a; 浏览器是我们日常使用的最重要的工具之一&#xff0c;它可以帮助我们获取信息、娱乐、学习、工作等。但是&#xff0c;传统的浏览器往往不能满足我们的个性化需求&#xff0c;也不能给我们提供智能化的服务。那么&#xff0c;有没有一种浏览器可以让我们的体…