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

网络基础 【UDP、TCP】

1.UDP

首先我们学习UDP和TCP协议 要从这三个问题入手

  • 1.报头和有效载荷如何分离、有效载荷如何交付给上一层的协议?
  • 2.认识报头
  • 3.学习该协议周边的问题

UDP报头 

UDP我们先从示意图来讲解,认识报头。

UDP协议首部有16位源端口号,16位目的端口号,16位UDP长度,16位UDP检验和。

16位的端口号,通过前面网络编程篇章,我们知道网络通信,必须要有源端口和目的端口号,2的16次方也就是 65536 所以端口号范围就是065535,这里不过多解释了。

16位UDP长度:UDP一次性最大能发送报文长度。16位 那么换算一下就是64KB。也就是说我们最大一次能发送数据就是64KB,对于现在的网络来说,64KB肯定不够用了。那超出的部分怎么办?

如果超过了64KB,那么就需要在应用层 手动的分包,多次发送,并在接收端手动拼装。

通过16位UDP长度,我们就可以将报文和数据分离,报头的长度是固定的,也就是8字节,那么报文长度减去8字节 不就是数据大小了吗? 

16位UDP检验和:虽然UDP不保证可靠性,但是对方收到报文也要进行检验,如果收到的数据不全?对方拿着也没有用,还不如直接丢弃。

总结:通过认识报头,我们知道了UDP报文的报头分别是什么意思以及它们的作用。也解决了报头和数据如何分离的问题。 

通过示意图还是不够直观的,为什么这么说?毕竟图片和代码是两个概念,很难联系在一起。为了大家能够理解的更深。下面先问大家一个问题

问题:UDP没有发送缓冲区,但是有接受缓冲区,既然有接受缓冲区那么就意味缓冲区里有着大量的UDP报文,既然是大量,那么OS要不要对这些报文进行管理?

 明显是要管理的,那么如何管理? 先描述再组织!

所以针对UDP报文管理就转变成了特定的数据结构的增删改查 ,虽然我们没有见过UDP在Linux操作系统内核是如何实现的,但是通过刚才讲解我们也可写一个伪代码。

struct udp_header
{uinnt32_t src_port;uinnt32_t dst_port;uinnt32_t length;uinnt32_t check_code;
{

 既然是自定义类型结构的变量,那么我们就可以在堆上开辟空间,在缓冲区利用链表进行增删改查

struct sk_buffer
{char* start;char* end;char* pos;int type;......struct sk_buffer* next;
}

UDP特点

UDP类似寄信,我们在现实过程中寄信,在寄信过程中不需要通知对方我给你寄信了,至于对方什么时候收到 ,我们不知道。人家回不回你的信也是一个问题(看人)!信内容是一次性发给对方的。总不可能你给人家寄信还分上下文吧?(也就是说我们数据是一次发给对方主机的,面向数据报) 

  • 无连接: 知道对端的IP和端口号就直接进行传输, 不需要建立连接;
  • 不可靠: 没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方, UDP协议层也不会给应用层返回任何错误信息;
  • 面向数据报: 不能够灵活的控制读写数据的次数和数量;

 基于UDP的应用层协议

  • NFS: 网络文件系统
  • TFTP: 简单文件传输协议
  • DHCP: 动态主机配置协议
  • BOOTP: 启动协议(用于无盘设备启动)
  • DNS: 域名解析协议

2. TCP 

TCP是非常重要的协议,没有之一! 我们学习TCP入手还是从刚才讲解UDP的那样一样。但是众所周知TCP是有接受缓冲区发送缓冲区,而UDP是没有的,这就意味着TCP有很多细节。

2.1 理解TCP缓冲区 

 我们平时用的write read send recv 函数 本质是拷贝函数,为什么这么说?我们在应用层调用这些系统接口,其实是应用层的缓冲区中数据通过这4个函数拷贝到TCP的缓冲区。也就是说 我们平时在应用层定义的那个缓冲区不是TCP的缓冲区。这也是为什么这些函数叫做系统调用接口,这正好对应了 数据层层向下交付,应用层的数据交付给传输层,反之向上也是一样。说到这里你就会有种熟悉感,这不就是我们之前讲的文件系统一样的吗?

以前是数据 通过系统调用接口 拷贝到OS缓冲区中,OS在将数据写入到文件中。(文件也是有文件缓冲区的)

TCP全称为 "传输控制协议(Transmission Control Protocol"). 传输 我们知道,TCP是个协议我们也知道,控制如何理解?

控制 就是对传输的控制。比如什么时候发? 发多少? 出错了怎么办? 

TCP是有接受\发送缓冲区的 发多少是由对方主机的缓冲区大小决定的,什么时候发由OS自主决定。 出错了TCP也有解决的办法。下面我们先从报文入手,认识报文。

2.2 TCP协议段格式

 学习报头 我们先解决数据分离 和 向上数据交付

通过16位的端口号我们就知道如何交付给那一个进程。16位源端口和目的端口号不多多说,前面UDP也讲过。

16位端口号的作用就是数据向上交付。

如何分离? 可是报头里没有报文的长度啊,但是有个4位首部长度。

这个4位首部长度是什么?

4位首部长度:也就是4个比特位,那么四位首部长度取值范围也就是0 到15 ,可是TCP报头就有20个字节。 这个15 不是明显不够? 4位首部长度是带单位的,就比如你的工资是2K?还是W? 而我们的首部长度的单位是4字节。所以首部长度真实大小是0到60字节  所以选项 最大的取值范围为40字节 (选项可以没有) 

所以数据和报头分离的采取的是固定长度+自描述字段。(报头大小固定20个字节,那么首部长度-减去固定长度 就得到数据的偏移量。这样我们就找到数据的起始位置。)                                      

16位窗口大小 :

先说作用:填写的是自己接受缓冲区的大小。

TCP要保证自己的可靠性,接受缓冲区的里面的内容 如果已经被打满了,上层不拿走数据,那么此时对方主机再发来数据,就要被覆盖。数据丢失,如何谈可靠性?所以就要有窗口大小。

注意:双方基于TCP协议通信的时候,互发消息都是完整的报文。且一定是携带的完整的TCP报头                                                                                                                                                       所以双方在进行通信的时候通过16位的窗口大小告诉了对方自己的接受缓冲区的大小是多大,这样对面就知道该发多少数据过来了。                                                                                                     

32位序号:                                                                                                                                        

TCP有自己的发送缓冲区,而这个发送缓冲区我们可以看做是一个非常大的数组。从应用层拷贝到缓冲区的数据天然就有了序号了,数组的下标就是数据的序号。

那序号存在意义?

有没有想过我们发送大量报文。前面发送的可能比后面发送的数据后到? 

如果数据乱序,本身就是一种不可靠。 所以序号存在的意义就是要让数据按序拷贝到对方的应用层。

围绕TCP的可靠性 TCP为了可靠性有了一些保证可靠的机制,比如应答机制。

32位确认序号: 

对方主机收到数据会确认序号 会在对方序号+1 比如:对方发送的数据是1000 那么我们作为接受方会发送一个确认讯号 也就是1001 对方收到应答机制ACK 就意味着 我们收到1001之前的所有数据。                                                                                                     

这里就有一个问题了 有了序号 为什么要确认序号? 我们确认直接复用序号不就可以了吗?

如果我们对序号确认,就发一个ACK 那当然没有问题,但是 如果我们是数据+应答?明显复用序号就不行了。 不要忘记了  TCP双方是对等,你给我发消息,我也要给你发消息。对方给我们发消息 我们刚好也要给对方发消息 而且要告诉对方我们收到他的消息,这种方式叫做捎带应答 ,最直观的就是提高了效率。

 6个标记位:

为什么要有6个标记位? TCP报文可是有不同的类型,而6个标记对应的不同类型报文,比如TCP有建立连接的 断开连接的,正常的数据通信。而这些场景注定了要有一些符号来标识报文的不同。

  • URG: 紧急指针是否有效
  • ACK: 确认号是否有效
  • PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走
  • RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段
  • SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段
  • FIN: 通知对方, 本端要关闭了, 我们称携带FIN标识的为结束报文段

对于ACK 不用多说 前面讲过 ,确认应答。 SYN/FIN 这个两个也不用多说,我们前面讲套接字的时候,调用connect 就是SYN建立连接,调用close 关闭文件描述符就是FIN

接受缓冲区的是有16位窗口大小的。也就是说缓冲区的最大值是固定的,如果对方一直不读取,而我们要发数据,但是对方接受缓冲区满了 这时候就要用到PSH

 TCP 虽然保证可靠性,但是TCP是允许建立连接失败的。

双方基于TCP协议通信的时候,建立连接是要3次握手,如果是A主动B发起连接SYN 那么 B此时回一个SYN+ACK,这时A就知道了 对方B已经收到我们的请求连接,而这时A再发一个ACKA就已经认为自己已经和B建立好连接了 所以A就开始发数据了,但是有没有一种可能,B并没有收到ACK。对于B来说我们3次握手还没有完成,过了几毫秒这时B收到对方的数据,就会将RST置为1发送完整的报文给A。而A收到了RST,就知道了 连接还没有建立。所以重新发起连接请求。

 URG 这个标记位我们用的并不多。它作用你可以认为是皇权特许,插位。 TCP为了保证数据的按序。但是有些数据比较急就需要对方优先处理。而此时配合16位紧急指针 就知道要处理紧急数据的位置。 紧急数据大小只有一个字节。毕竟TCP要保证可靠性,不能乱了主次。

16位紧急指针:就是紧急数据的偏移量 

2.3 TCP可靠机制

 确认应答机制

前面已经提到 可以看前面关于序号的内容。

 超时重传机制

  • 主机A发送数据给B之后, 可能因为网络拥堵等原因, 数据无法到达主机B;
  • 如果主机A在一个特定时间间隔内没有收到B发来的确认应答, 就会进行重发;

这个就是超时重传机制,但是上面的情况是对于B来说数据丢失,还有可能是B收到数据了,对于A来说ACK丢包了?

 关于超时重传机制存在,对于应答丢失这种情况,那么对于对方主机B就会收到大量重复的报文,重复大量的报文,本身也是一种不可靠的行为。但是超时重传机制又不能不存在。没有超时重传机制TCP的可靠性就无法保证,有没有去重的办法?

前面讲的序号就是去重的报文的,因为在对方的接受缓冲区中之前发来的数据是一直存在的(上层没有拿走数据),根据序号就我们知道对方重新发来报文进行对比,序号一致那么就是重复报文。

那关于超时重传,超时多少重传?

  • 最理想的情况下, 找到一个最小的时间, 保证 "确认应答一定能在这个时间内返回".
  • 但是这个时间的长短, 随着网络环境的不同, 是有差异的.
  • 如果超时时间设的太长, 会影响整体的重传效率;
  • 如果超时时间设的太短, 有可能会频繁发送重复的包;

所以超时重传机制,重传是动态的。随着次数的增多,后面再发送时间会增加,如果超时重传时间太长,那么对方网络的出了问题,这时就关闭我们已经和对方建立好的连接。

连接管理机制

基于TCP协议通信 双方在进行连接时,会进行三次握手,四次挥手。面试题!!!

那什么又是三次握手,四次挥手?

三次握手 

 基于上面这张图,我们一一讲解,首先我们先看到客户端应用层和服务端应用层 fd write 和read 等等这些函数,是不是很熟悉? 这就是我们前面套接字。

那么客户端和服务器如果是基于TCP 协议通信,此时主动的一方会发起建立连接的请求。(大部分都是客户端发起建立连接的请求 这里我们默认都是客户端发起请求。)

客户端发起请求,会发送一个SYN,(这就是一次了)  服务器收到SYN 就会回一个SYN +ACK (这就是两次了) , 然后 客户端收到 SYN +ACK   再发送一个ACK给服务端。(这就是第三次了)。

TCP为了保证可靠性 一来一回都会发送ACK。这就是3次握手 

SYN_SENT 这个状态码叫做 同步发送 同理 SYN_RCVD 叫做 同步收到ESTABUSHED 说明本地连接已经建立好了。

 这里要强调的有两个函数 connect 和 accept 。当我们客户端调用connect 时,也就是请求连接。会被阻塞,因为双方建立连接,是由双方的操作系统自主决定的,也就是说,当客户端收到SYN +ACK  此时 ESTABUSHED  被设置。如果 建立连接的期间 ESTABUSHED  没有被设置,那么connect 一直都是阻塞状态,直到收到SYN +ACK  

同样的 accept 也是一样, 如果 本地连接没有建立好。那么上层调用accept 就会被阻塞,下层都没有连接拿上来能够用的,当然会被阻塞。

四次挥手 

当我们建立好连接 就是数据 发送了 ,你给我发送一个数据,我给你一个应答。

如果双方都没有要发的数据了,那么此时双方就会断开连接。 

断开连接 和 建立连接不一样, 毕竟 建立连接 是一方主动,一方被动。 断开连接 是要双方协商之后才会断开,就如同生活中,小明追小美一样,一方被动,一方主动。当他们结婚以后,再离婚,可不是说谁 我要离婚,就离婚了,而是 要经过小明和小美一致同意之后,才会离婚。 

那么客户端如果没有数据要发了,调用 close 此时客户端就会发送一个FIN 给 服务端,(这就是一次)服务端收到之后 再发送ACK给 客户端(这是第二次) ,如果服务端没有要发的数据了,那么服务端就会给客户端发送FIN(这是第三次)客户端收到服务端的FIN 会发送ACK给服务端 (这是第四次)。

这就是传说中的4次握手。

状态码后面讲 ,我们先说为什么要三次握手,四次挥手。 

首先为什么要握手三次?我先说原因 验证全双工,最小奇数次可以将连接管理的成本嫁接到客户端。  

TCP 是平等的,你给我发,我也要给你发,所以当客户端请求服务端建立连接发送完整报头将SYN置为1 ,对方收到之后 回一个ACK,这就证明了 客户端给服务器发送消息没有问题,前面也说过,你来我往,你给我发没有问题,但是我给你发有没有问题也是需要验证的。所以客户端再发送一个ACK给服务端 如果服务端收到,这就证明了 服务端给客户端发消息也没有问题。

有人说一次可不可以?

我们设想一下 如果是一次SYN 那么客户端 就每发一次服务器收到就要建立连接。一台机器就可以给服务器建立大量的连接。连接再内核中也是一种数据结构,开辟这种结构体,是要耗费内存的,连接的管理也有成本的。一次握手就是SYN洪水。服务器压力会很大。

那两次?

如果是两次,也是优先给服务端建立连接动作,当服务器发送ACK 本地连接就建立好了,如果客户端不回消息,服务端会将这个连接维持一段时间,只是几台机器还好说,关键是服务器一对多,那么如果有大量连接异常,服务器维持成本就会很大。所以对于这种情况来说,最好是客户端做出让步,毕竟客户端只有自己一个连接。

三次就是最小寄数次 将连接的管理成本嫁接到了客户端。有人说5次 7次 可不可以? 这就有点画蛇添足了。一次就能做好的事情,为什么要返工再做一次或者是多次?

四次 其实3次握手也叫四次握手 因为 按照常理 客户端发SYN 服务端收到 发ACK 然后服务端也要和客户端建立连接,发送SYN 客户端收到之后,回一个ACK 这其实就是4次。 只不是 服务端那次被捎带应答了,也就是 SYN 和 ACK 被压缩成一次了。故而叫做三次握手。

那为什么断开连接是4次 不能三次吗?  

这是因为 发送数据 双方都有可能发,所以断开连接必须两次。一来一回就是4次。三次只有极端情况才有可能,客户端想要断开,刚好服务器也没有要发的。而这种几率很小,毕竟服务器是被动的,那么就可以将FIN 和 ACK 压缩成一次。

理解TCP连接时的状态变化

双方建立连接时,是双方OS自主决定的,也就是说和accept没有任何关系。

 

listen第二参数是连接管理的最大长度,就是一个队列。如果服务器listen第二个参数设置太小 我们假设为9。 那么连接的最大长度就是10 假设我们已经连接了10个客户端,那么第11个客户端和服务器进行连接时,如果上层accept 没有拿走连接 还是10 个。那么 在服务端来说,连接并没有建立好,此时会将第11个客户端的请求建立的连接,状态还是为 SYN/ RCVD 而客户端则认为自己是建立好了连接 将自己的状态码设置为ESTABLISHED

SYN/ RCVD要变为 ESTABLISHED 一定是条件满足了,条件不满足状态不会发送变化。

TCP保证可靠性,原来的全连接队列已经满了。那这个连接会放在那里?会放在半连接队列里

对于服务端来说,处于 SYN/ RCVD的状态的连接,不会维护太长的时间。  半连接不重要直接跳过。

这里关于listen的参数就有两个问题了

一是为什么不能没有? 二是为什么不能太长。

先说为什么要有,就好比我们周末去比较火的饭店里吃饭,如果去时间比较晚了,你会发现在前面还有人排队。如果一个饭店没有排队机制,也就是饭店门口没有放座椅话,那么这些客人就会走,对于饭店来说,营业额就会大大降低。那么对于互联网来说也是一样,当双11或者双12时。流量访问巨大,那么对于服务器压力来说是比较大的,如果没有这个机制,人家客户连接不上你的服务器,还怎么买东西?如果我们有了这个管理连接的数据结构那么我们就可以最大化满足客户连接请求。当服务器的压力缓解了,立马就能调用accept。

 既然有了为什么不能太长?这个就非常简单了,连接被打满一定是上层出了问题了。比如处理上层的计算任务,而这个任务又太大了,导致服务器的压力剧增。注意这是一种数据结构,也是要耗费内存开辟空间的,如果我们设置长度太多,服务器本来就忙不过来了,还要消耗一部分资源来维护这个连接队列,那么就得不偿失了。

 基于刚才的情景,这就是传说中的连接建立不一致的问题。        


这里我们以服务器主动断开的背景来讲。

当服务器主动断开连接时,会将自己的状态设置 FIN_WAIT1 此时作为客户端收到了客户端FIN报文,那么会将自己的状态设置为CLOSE_WAIT状态 收到之后给予应答ACK。服务端如果收到了ACK会将自己的状态设置为FIN_WAIT2  当客户端也要断开连接时,也会发送FIN,当对方收到了我们发送的FIN ,此时就会将状态设置为TIME_WAIT 当我们收到了服务端发来的ACK,此时4次挥手才算完成。也就是正常的断开连接。

理解TIME_WAIT状态

首先只有主动断开连接的一方才会有TIME_WAIT,从字面意思来看就是等待一段时间,也就是说连接并没有彻底的断开,IP 和 Port 正在被使用。

 我先说理由:

1. 让通信双方历史数据得以消散。

2. 断开连接时,双方4次挥手具有较好的容错性。

为什么需要TIME_WAIT状态

  1. 确保数据完整性:确保所有重复的TCP段在网络中消失,避免新连接被旧的重复数据干扰。
  2. 防止端口耗尽:如果立即释放端口,可能会与其他服务冲突,因为TCP连接是基于四元组(源IP、源端口、目的IP、目的端口)来识别的。虽然这种概率很小
  3. 实现可靠传输:确保TCP连接的终止是可靠的,不会因为网络问题导致连接错误地被认为已经关闭。

那等多久?

  • 2MSL等待TIME_WAIT状态会持续一个称为“最大报文段生存时间”(Maximum Segment Lifetime,MSL)的两倍时间。MSL是任何TCP段在网络中生存的最大时间。这个等待时间确保了即使在网络延迟或TCP段被复制的情况下,所有的重复TCP段都能在这段时间内消失。
  • 资源占用:在TIME_WAIT状态下,系统会为每个处于此状态的连接保留资源(如端口号),直到2MSL时间结束。这可能会导致端口耗尽,特别是在高并发的服务器上。
  • 快速回收:在某些操作系统中,可以通过设置SO_REUSEADDR套接字选项来允许应用程序快速重用处于TIME_WAIT状态的端口。可以让服务器立即重启,前面说过IP和Port正在被使用,而端口号只能被一个进程绑定,如果不设置,我们会绑定失败的。

 注意:最大报文段生存时间 和 最大传送时长是两个不同概念, 报文在网络存活的时间就是MSL,而最大传送时长是 A端 到B 端 报文传送时间,最大传送时长的时间也就几毫秒,而最大报文段生存时间 这个没有定数,以Linux 为例 一般是60S 。也就是说这个是秒级的。当然这个也可改

流量控制

接收端处理数据的速度是有限的 . 如果发送端发的太快 , 导致接收端的缓冲区被打满 , 这个时候如果发送端继续发送 , 就会造成丢包, 继而引起丢包重传等等一系列连锁反应 .
因此 TCP 支持根据接收端的处理能力 , 来决定发送端的发送速度 . 这个机制就叫做 流量控制 (Flow Control) ;

那我们怎么知道第一次发送数据时,不会打满对面的接受缓冲区? 也就是合理的发送数据?

不要忘记了 TCP在建立连接进行3次握手时,双方就已经告诉了自己各自16位窗口大小。所以在主动建立连接的一方第三次时,其实就可以发送数据了加捎带应答。

 那如果双方在后序的发送数据往来时,一方的缓冲区被打满了,这时另一方基于流量控制的机制,那么就不会再发送数据了,为了提高效率,那如何知道对面的缓冲区已经被上层读取了?

作为发送数据的一方会定期发送一个窗口探测的报头,询问对方。 而接受的一方也是一样缓存区的数据被上层读走了,会立马向对方发送一个窗口更新的报头。

 滑动窗口

背景知识

前面讲过TCP为了可靠性,发出的报文如果没有收到对应的ACK,那么这个报文还是会存在到自己的发送缓冲区。 

 其二TCP发送报文并不是我们想象中的发一个报文收一个ACK这样效率太过低下,而是可以串行的发送大量的报文。也就意味着,需要串行的收到大量的ACK,这个就好比 微信发送消息一样,你可以在对面没有回你消息前,一次性可以发送多条消息。

那么大家肯定就会有疑问了,那已经发出未收到ACK的报文是存放在发送缓冲区的那个位置?

首先TCP将发送缓冲区分成了3个区域,第一个区域为已发送已确认,第二区域为以发送未确认,第三个区域为待发送。

 

而这个第二个区域就是传送中的滑动窗口。而已发送未确认的报文是在滑动窗口这个区域里面,正是因为有了滑动窗口我们才可以发送大量的报文给对方主机。

那如何划分这些区域?前面讲过TCP缓冲区,就是一个数组,我们利用数组的下标充当指针,一个开始,一个结束,滑动窗口本质就是指针的右移,这个就是双指针算法。区域不就划分好了吗?

 

  • 收到第一个ACK, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推;
  • 操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉;
  • 窗口越大, 则网络的吞吐率就越高;

 既然是串行发送大量报文,那如果中间的报文丢了怎么办?就比如下面这种情况

情况1:数据包已经抵达,而ACK被丢了。 

首先我们要明白确认序号的意义,如果中间的丢了这种情况下, 部分ACK丢了并不要紧, 因为可以通过后续的ACK进行确认; 有了确认序号,如果我们收到了2000以后确认序号,那么1001 到2000 我们也是收到的。

情况2:如果是数据直接就丢了?

 如上图所示1001——2000的数据丢了,我们串行发送大量报文,对于2000以后的报文,对应的ACK序号还是1001,如果我们收到的ACK重复了3次,会立马补发1001——2000的报文。而这个机制叫做快重传

这里提出了快重传想必大家会有疑问,有了快重传为什么还要有超时重传

首先快重传存在的意义是提高效率,而快重传这个机制 触发是需要条件的,也就是上面说的3次重复的ACK。想一想如果到了后期数据没有这么多了,就一两条数据发送,能触发快重传吗?如果没有了超时重传,对于这种情况来说,后面的数据可能就收到不到了。

那这个滑动窗口 右移 如何移动?

首先窗口的移动只有右移,没有左移。窗口大小是动态的变化的,也就是说窗口大小不仅取决于对方接受窗口的能力,还要看自己的拥塞窗口(这个后面讲,暂时认为是对方的接受窗口)。

前面说,滑动窗口算法实现是基于双指针算法,如果左指针移动,右指针不动,那么这个滑动窗口必然是缩小的,如果左右指针都移动,那么滑动窗口范围要么变大要么变小(左移动宽度大于右的,那么就是缩小,反之变大),

如果一直都是左移动,右不变,那么滑动窗口就变为0了。(如果为0意味对方上层一直没有读取数据,而且缓冲区被打满。)

 那如何现实滑动窗口?

既然是双指针算法,那我们肯定要定义两个指针,start 和 end 。 那如何确定这个两个指针的起始位置?

我们可以根据TCP的确认序号来确认, int start = 确认序号,end = 确认序号+ 对方窗口大小(暂时认为)。

所以到这里你明白了流量控制的实现是基于滑动窗口的。 

滑动窗口会不会越界?

当然不会越界 TCP采取了类似环状的算法,也就是取模运算。

延迟应答 

如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小,为什么这么说,因为虽然对方主机收到了我们发送的数据,但是对方主机上层也就是应用层不一定马上就把数据拿上去了。所以缓冲区数据还是有,那么就意味着对方主机不能进行窗口更新。

一定要记得 , 窗口越大 , 网络吞吐量就越大 , 传输效率就越高 . 我们的目标是在保证网络不拥塞的情况下尽量提高传输效率;

所以延迟应答的作用就是提高传输的效率,本质就是在赌上层能够立即讲数据读走。

那么所有的包都可以延迟应答么 ? 肯定也不是 ;
  • 数量限制: 每隔N个包就应答一次;
  • 时间限制: 超过最大延迟时间就应答一次;  
具体的数量和超时时间 , 依操作系统不同也有差异 ; 一般 N 2, 超时时间取 200ms

 拥塞控制

虽然TCP很可靠,但是所有策略都是在两台机器上起作用,也就是说如果是网络出现了问题,某些机制的触发还有可能造成资源的浪费,网络出现了问题,超时重传是没有意义的而且还会加重网络拥塞。
如果是在通信时,出现了大量的丢包情况,那么一定是网络出现了问题,面对网络出现了问题,TCP当然也替我们考虑到了网络的问题。这时TCP的拥塞控制就会触发。

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

  • 此处引入一个概念程为拥塞窗口
  • 发送开始的时候, 定义拥塞窗口大小为1;
  • 每次收到一个ACK应答, 拥塞窗口加1;
  • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口;

所以真正的滑动窗口的大小是取(滑动窗口的有效数据,拥塞窗口)最小值。 

 像上面这样的拥塞窗口增长速度, 是指数级别的. "慢启动" 只是指初使时慢, 但是增长速度非常快.

  • 为了不增长的那么快, 因此不能使拥塞窗口单纯的加倍.
  • 此处引入一个叫做慢启动的阈值
  • 当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长

 

如上图所示,TCP开始启动的时候, 慢启动阈值等于窗口最大值;初始值是16 当这个值为24时,出现了网络拥塞,此时用算法乘法减小(对半减)24变成12 同时拥塞窗口置回1;。 下次在慢开始时,如果这个值到了12了,那么后面就是线性方式增长。 

3. 面向字节流 

那什么是字节流?

一直都说TCP是面向字节流的,你可以把字节当成水一样。

其实我们上层发送的数据,不管是几个或者单个,到了下层也就是TCP。转化成二进制,几个报文都变成了二进制数据,那么也就意味着没有报文概念了,全部揉在一起,放在TCP的缓冲区中,通过滑动窗口一次发送大量的数据过去,那么对方收到之后就如同你家水龙头打开一样,水流就出来了。至于这个水流是由河水 还是 净化后的自来水,TCP各自的接受缓冲区不关心,真正关心数据来源以及如何区分这些水,那是上层来决定的。

所以我们上层为什么要自己定制协议,方便拿到数据之后,分析解析数据。

为什么TCP是面向字节流的?

这是因为TCP既有发送缓冲区,又有接受缓冲区,也就意味着读写可以不一一匹配。

由于缓冲区的存在,我们调用read 或者 write ,假设我们读取100字节,那么你可以一次性读100个字节,也可以100次读一个字节。对于write也是一样,但是UDP就不行。

 4.粘包问题

        由于TCP是面向字节流,上层的数据都揉在一起了,加上滑动窗口的存在,必定会有报文的数据一部分没有在滑动窗口内,那么发送过去,对方可能收到的就不是一个完整的报文。这个就是粘包问题。

如何解决?

确定好报文之间的边界 

对于这个问题前面博客已经讲过了。这里总结一下吧

  • 定长报文
  • 特殊字符
  • 自描述字段+定长报文
  • 自描述字段+特殊字符。 

注意:而这个东西也是属于我们自定义协议的一个部分,不要和序列化和反序列化搞混了。

5. TCP异常情况 

进程被终止,那么TCP 建立的连接也是随进程一样释放了,因为文件的生命周期是随进程的。

所以机器重启这种情况也是和进程终止一样的。

那如果是网线掉了,或者机器掉电了?

对于这种情况来说:接收端认为自己的建立的连接还存在。但是如果有写入操作那么接受端就会发现建立的连接不存在了,这就是传说中的连接建立不一致的问题,那么接收端就会把标志位RST设置.

即使没有写入操作, TCP 自己也内置了一个保活定时器 , 会定期询问对方是否还在 . 如果对方不在 , 也会把连接释放 .

6.文件描述符与socket的关系

文件描述符其实就是个指针数组的指针,而这个数组里面的指针指向是一片内存区域的(比如文件缓冲区,TCP的缓冲区),那么在代码中,就是结构体套结构体,文件系统就是stuct *file 那么网络就是 struct *sock ,那么通过指针指向不同的结构体,那么就能执行不一样的代码,如果是本地指针指向的是 *file ,那么对于就是本地的增删改查的方法,如果指向的是*sock那么对应的就是网络中增删改查。

而这个两个结构体都内嵌相对应方法的结构体。

所以这就是C语言的多态。

这里只是简单的说了一说,感谢兴趣的读者可以去看内核的源码。

当然 应用层到数据链路层 每一层都有不同处理报文的方法,所以这里处理方式也是上面一样,指针移动,(这里指针而不是上面的指针,而是内嵌的结构体里面处理增删改查的方法指针,)所以在TCP缓冲区中,每一层数据其实不是向上交付而是通过指针的移动,让人感觉就是向上交付。

 总结

为什么 TCP 这么复杂 ? 因为要保证可靠性 , 同时又尽可能的提高性能 .

可靠性 :
  • 校验和
  • 序列号(按序到达
  • 确认应答
  • 超时重发
  • 连接管理
  • 流量控制
  • 拥塞控制
提高性能 :
  • 滑动窗口
  • 快速重传
  • 延迟应答
  • 捎带应答
其他 :
定时器 ( 超时重传定时器 , 保活定时器, TIME_WAIT 定时器等 )

相关文章:

网络基础 【UDP、TCP】

1.UDP 首先我们学习UDP和TCP协议 要从这三个问题入手 1.报头和有效载荷如何分离、有效载荷如何交付给上一层的协议?2.认识报头3.学习该协议周边的问题 UDP报头 UDP我们先从示意图来讲解,认识报头。 UDP协议首部有16位源端口号,16位目的端…...

python旅游推荐系统+爬虫+可视化(协同过滤算法)

✅️基于用户的协同过滤算法 ✅️有后台管理 ✅️2w多数据集 这个旅游数据分析推荐系统采用了Python语言、Django框架、MySQL数据库、requests库进行网络爬虫开发、机器学习中的协同过滤算法、ECharts数据可视化技术,以实现从网站抓取旅游数据、个性化推荐和直观展…...

数据结构 树的存储和遍历

一、树的定义 树的定义 树型结构是⼀类重要的⾮线性数据结构。 • 有⼀个特殊的结点,称为根结点,根结点没有前驱结点。 • 除根结点外,其余结点被分成M个互不相交的集合T1 、T2 、...、Tm T,其中每⼀个集合⼜是⼀棵树&#xff0c…...

《解锁自然语言处理:让公众正确拥抱AI语言魔法》

在当今数字化浪潮中,自然语言处理(NLP)技术作为人工智能领域的璀璨明珠,正以惊人的速度融入我们的生活。从智能语音助手到智能客服,从机器翻译到内容创作辅助,NLP技术无处不在。然而,如同任何强…...

qt实习总结

创建一个滑动条 QSlider *slider new QSlider(Qt::Vertical); //创建一个垂直方向的 进度条 带有上下箭头的输入框 QSpinBox 提供了一个带有上下箭头的输入框 垂直 水平怎么说 horizontal vetical 布局知识 BtnLayout->addWidget(AmendBtn); BtnLayout->addWidg…...

HTTP的“对话”逻辑:请求与响应如何构建数据桥梁?

一、前言 作为现代互联网通信的基石,HTTP协议定义了客户端与服务器之间的“对话规则”。每一次网页加载、API调用或文件传输的背后,都离不开精心构造的HTTP请求与响应。请求中封装了用户的意图——从请求方法、资源路径到提交的数据;响应则承…...

Docker 镜像标签使用

写在前面 当使用命令 docker pull mysql 拉取镜像时,其实等价于如下命令 docker pull mysql:latest latest 是默认的标签,字面上理解为最新版本的镜像,实质上 latest 只是镜像的标签名称,跟具体某个版本号地位一样,…...

C#异步/多线程编程中Task对象强大的功能介绍。

在 C# 的异步编程中,Task 是一个非常重要的类,它表示一个异步操作。Task 类提供了许多方法,用于管理、控制和组合异步操作。以下是 Task 类中一些常用方法的详细讲解及其功能。 1. Task.Run 功能:将指定的代码块调度到线程池中异步…...

DDD聚合在 ASP.NET Core中的实现

在ASP.NET Core中实现DDD(领域驱动设计,Domain-Driven Design)聚合通常涉及到几个关键步骤,包括定义领域模型、实现领域服务、使用仓储模式等。以下是如何在ASP.NET Core应用中实现DDD聚合的一些步骤和示例。 1. 定义领域模型 首…...

docker push镜像到阿里云

阿里云账号 阿里云-计算,为了无法计算的价值 开通个人镜像容器 进入控制台,试用容器 实例列表界面 点击上图中的个人,个人版特性 创建个人版: 个人版实例界面: 设置密码 个人版实例: 创建镜像仓库 如上…...

移动通信发展史

概念解释 第一代网络通信 1G 第二代网络通信 2G 第三代网络通信 3G 第四代网络通信 4G 4g网络有很高的速率和很低的延时——高到500M的上传和1G的下载 日常中的4G只是用到了4G技术 运营商 移动-从民企到国企 联通-南方教育口有人 电信 铁通:成立于 2000 年…...

Transformer笔记

Transformer笔记 文章目录 Transformer笔记模型架构核心技术多头注意力机制概念数学概念单头注意力机制代码 基于位置的前馈网络残差连接和层规范化 编码器解码器 特点:Transformer模型完全基于注意力机制,没有任何卷积层或循环神经网络。之前Transforme…...

【学习资源】时间序列数据分析方法(1)

时间序列数据分析是一个有趣的话题,让我们多花一些时间来研究。此篇为第一篇文章。主要介绍特征提取方法、深度学习时序数据分析模型、参考资源。期望能帮助大家解决工业领域的相关问题。 1 特征提取方法:信号处理 (来源:INTELLIGENT FAULT DIAGNOSIS A…...

PHP 文件与目录操作

PHP 学习资料 PHP 学习资料 PHP 学习资料 在 PHP 编程中,文件与目录操作是一项基础且重要的技能。无论是处理用户上传文件、生成日志,还是管理项目中的各类资源,都离不开对文件和目录的操作。PHP 提供了丰富的内置函数,方便开发…...

PostgreSQL认证指南

PostgreSQL 作为一款强大的开源关系型数据库,深受开发者和企业的青睐。获得 PostgreSQL 专家认证,不仅能提升个人在数据库领域的专业能力,还能为职业发展增添有力筹码。下面为大家详细介绍 PostgreSQL 专家认证的学习路径。 一、深入理解基础…...

hive全量迁移脚本

#!/bin/bash #场景:数据在同一库下,并且hive是内部表(前缀的hdfs地址是相同的)#1.读取一个文件,获取表名#echo "时间$dt_jian_2-------------------------" >> /home/hadoop/qianyi_zengliang/rs.txt#…...

Qt5开发入门指南:从零开始掌握跨平台开发

目录 Qt框架概述 开发环境搭建 基础语法与核心机制 第一个Qt窗口程序 常见问题解答 一、Qt框架概述 1.1 什么是Qt? Qt是一个1995年由挪威Trolltech公司开发的跨平台C图形用户界面应用程序框架。最新Qt5版本主要包含: GUI模块:支持Wind…...

WPF的Prism框架的使用

安装Prism.DryIoc库&#xff1a; Prism的区域和模块化&#xff1a; 一个区域可以显示一个用户控件 一个模块就是一个项目&#xff0c;也就是一个类库 动态切换用户控件的案例&#xff1a; <Grid><Grid.RowDefinitions><RowDefinition Height"auto"…...

【机器学习】线性回归 线性回归模型的损失函数 MSE RMSE MAE R方

【机器学习系列】 KNN算法 KNN算法原理简介及要点 特征归一化的重要性及方式线性回归算法 线性回归与一元线性回归 线性回归模型的损失函数 多元线性回归 多项式线性回归 线性回归模型的损失函数 V1.0损失函数的计算方法损失函数的分类MSE (Mean Squared Error)RMSE (Root Mea…...

服务器部署DeepSeek,通过Ollama+open-webui部署

1. 安装ollama 1.1. linux 安装 Ollama是目前常用的AI模式部署的第三方工具&#xff0c;能一键部署deepSeek Ollama官方网址https://ollama.com/ 选择Download下载对应的服务版本 服务器选择Linux&#xff0c;下面是下载代码 curl -fsSL https://ollama.com/install.…...

Java 大视界 -- 开源社区对 Java 大数据发展的推动与贡献(91)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…...

【Vue3源码解析】应用实例创建及页面渲染

下载源码 git clone https://github.com/vuejs/core.git写该文章时的Vue版本为&#xff1a; "version": "3.5.13",这里要注意 pnpm 的版本不能太低&#xff0c;我此时的版本为 9.15.4。更新 pnpm 版本&#xff1a; npm install -g pnpm然后安装依赖&…...

云原生AI Agent应用安全防护方案最佳实践(上)

当下&#xff0c;AI Agent代理是一种全新的构建动态和复杂业务场景工作流的方式&#xff0c;利用大语言模型&#xff08;LLM&#xff09;作为推理引擎。这些Agent代理应用能够将复杂的自然语言查询任务分解为多个可执行步骤&#xff0c;并结合迭代反馈循环和自省机制&#xff0…...

人工智能 - 主动视觉可能就是你所需要的:在双臂机器人操作中探索主动视觉

AV-ALOHA 系统使用用于 AV 的 VR 耳机实现直观的数据收集&#xff0c;并且 用于作的 VR 控制器或引线臂。这有助于捕捉全身和头部 远程作我们的真实和模拟系统的运动&#xff0c;记录来自 6 个的视频 不同的摄像头&#xff0c;并为我们的 AV 仿制学习策略提供训练数据。 加州大…...

Ubuntu 下 systemd 介绍

系列文章目录 Linux内核学习 Linux 知识&#xff08;1&#xff09; Linux 知识&#xff08;2&#xff09; WSL Ubuntu QEMU 虚拟机 Linux 调试视频 PCIe 与 USB 的补充知识 vscode 使用说明 树莓派 4B 指南 设备驱动畅想 Linux内核子系统 Linux 文件系统挂载 QEMU 通过网络实现…...

两个实用且热门的 Python 爬虫案例,结合动态/静态网页抓取和反爬策略,附带详细代码和实现说明

在这个瞬息万变的世界里&#xff0c;保持一颗探索的心&#xff0c;永远怀揣梦想前行。即使有时会迷失方向&#xff0c;也不要忘记内心深处那盏指引你前进的明灯。它代表着你的希望、你的信念以及对未来的无限憧憬。每一个不曾起舞的日子&#xff0c;都是对生命的辜负&#xff1…...

Softing线上研讨会 | 自研还是购买——用于自动化产品的工业以太网

| 线上研讨会时间&#xff1a;2025年1月27日 16:00~16:30 / 23:00~23:30 基于以太网的通信在工业自动化网络中的重要性日益增加。设备制造商正面临着一大挑战——如何快速、有效且经济地将工业以太网协议集成到其产品中。其中的关键问题包括&#xff1a;是否只需集成单一的工…...

Jetson Agx Orin平台preferred_stride调试记录--1924x720图像异常

1.问题描述 硬件: AGX Orin 在Jetpack 5.0.1和Jetpack 5.0.2上测试验证 图像分辨率在1920x720和1024x1920下图像采集正常 但是当采集图像分辨率为1924x720视频时,图像输出异常 像素格式:yuv_uyvy16 gstreamer命令如下 gst-launch-1.0 v4l2src device=/dev/video0 ! …...

从2025年起:数字化建站PHP 8.1应成为建站开发的基准线

在数字化浪潮席卷全球的今天,PHP语言仍然保持着Web开发领域的核心地位。根据W3Techs最新统计,PHP驱动着全球78.9%的已知服务端网站。当时间指向2025年,这个拥有28年历史的编程语言将迎来新的发展里程碑——PHP 8.1版本应成为网站开发的最低基准要求,这不仅是技术迭代的必然…...

电动汽车电池监测平台系统设计(论文+源码+图纸)

1总体设计 本次基于单片机的电池监测平台系统设计&#xff0c;其整个系统架构如图2.1所示&#xff0c;其采用STC89C52单片机作为控制器&#xff0c;结合ACS712电流传感器、TLC1543模数转换器、LCD液晶、DS18B20温度传感器构成整个系统&#xff0c;在功能上可以实现电压、电流、…...

20240914 天翼物联 笔试

文章目录 1、行测知识1.11.21.31.41.51.61.71.81.91.101.111.121.131.141.152、专业知识2.12.22.32.42.52.62.72.82.92.102.112.122.132.142.153、编程题3.13.2岗位:嵌入式开发工程师(上海) 题型:15 道行测知识,15 道专业知识,2 道编程题 注意:本文章暂无解析,谨慎分…...

前端高级面试题

以下是一些前端高级面试可能涉及到的内容: 一、前端工程化 如何构建一个适合大型团队的前端代码规范和构建流程? 答案: 代码规范方面: 使用ESLint结合Prettier来统一JavaScript和CSS(包括预处理器如Sass或Less)的语法风格。例如,规定变量命名采用驼峰命名法,函数名要有…...

【nvidia】NCCL禁用P2P后果权衡

通信bound还是计算bound&#xff1f; 计算bound场景&#xff1a; 模型参数量较小&#xff08;如参数量未超出单卡显存容量&#xff0c;使用纯数据并行&#xff09;或计算密度极高&#xff08;如大batch size下的矩阵运算&#xff09;时&#xff0c;A100的计算能力&#xff08…...

哈希表(C语言版)

文章目录 哈希表原理实现(无自动扩容功能)代码运行结果 分析应用 哈希表 如何统计一段文本中&#xff0c;小写字母出现的次数? 显然&#xff0c;我们可以用数组 int table[26] 来存储每个小写字母出现的次数&#xff0c;而且这样处理&#xff0c;效率奇高。假如我们想知道字…...

unity学习46:反向动力学IK

目录 1 正向动力学和反向动力学 1.1 正向动力学 1.2 反向动力学 1.3 实现目标 2 实现反向动力 2.1 先定义一个目标 2.2 动画层layer&#xff0c;需要加 IK pass 2.3 增加头部朝向代码 2.3.1 专门的IK方法 OnAnimatorIK(int layerIndex){} 2.3.2 增加朝向代码 2.4 …...

夜莺监控发布 v8.beta5 版本,优化 UI,新增接口认证方式便于鉴权

以防读者不了解夜莺&#xff0c;开头先做个介绍&#xff1a; 夜莺监控&#xff0c;英文名字 Nightingale&#xff0c;是一款侧重告警的监控类开源项目。类似 Grafana 的数据源集成方式&#xff0c;夜莺也是对接多种既有的数据源&#xff0c;不过 Grafana 侧重在可视化&#xff…...

asio的使用

1、下载 性能测试&#xff1a;https://github.com/huyuguang/asio_benchmark 2、基本使用 2.1 TCP 1、客户端&#xff1a; 2、服务端&#xff1a; 2.2 UDP单揪 boost的asio接收单路大数据量udp包的方法 1、发送&#xff1a; 2、接收&#xff1a; #include "Circled…...

PHP语法完全入门指南:从零开始掌握动态网页

本文专为零基础新手设计,通过5000字详细讲解带你系统学习PHP语法。包含环境搭建、基础语法、实战案例,并附20+代码示例。阅读后你将能独立开发简单动态网页! 一、PHP开发环境搭建(新手必看) 1.1 为什么需要搭建环境? PHP是服务器端脚本语言,需要运行在服务器环境中。推…...

WPF快速创建DeepSeek本地自己的客户端-基础思路版本

开发工具&#xff1a;VS 2015 开发环境&#xff1a;.Net 4.0 使用技术&#xff1a;WPF 本篇文章内容&#xff1a; 本地部署DeepSeek以后一般使用网页工具&#xff08;如Chatbox&#xff09;或者DOS窗口与其对话。本篇文章使用WPF创建一个基础版的对话工具。 一、搭建本地DeepS…...

Win7本地化部署deepseek-r1等大模型详解

参考链接 在Windows 7操作系统&#xff0c;基于llama.cpp本地化部署 deepseek-r1模型的方法 2025-02-08 2G内存Windows7运行deepseek-r1:1.5b 这两个链接写的可能不够详细&#xff0c;有同学私信问实现过程&#xff0c;这里进一步解释一下。 一、准备 需要准备的大模型、工具…...

分享一个解梦 Chrome 扩展 —— 周公 AI 解梦

一、插件简介 周公 AI 解梦是一款基于 Chrome 扩展的智能解梦工具&#xff0c;由灵机 AI 提供技术支持。它能运用先进的 AI 技术解析梦境含义&#xff0c;为用户提供便捷、智能的解梦服务。无论你是对梦境充满好奇&#xff0c;还是想从梦境中获取一些启示&#xff0c;这款插件都…...

国产Linux OS:网络性能调优关键内核参数

国产Linux OS&#xff1a;网络性能调优关键内核参数 参数列表 这些参数是Linux系统中用于网络性能调优的关键内核参数&#xff0c;它们控制了网络接口和TCP协议栈的行为。合理调整这些参数可以根据具体的应用场景和网络条件优化系统的网络性能。 sysctl net.core.rmem_max sy…...

DeepSeek接口联调(postman版)

第一步&#xff1a;获取API key 获取APIkeys链接https://platform.deepseek.com/api_keys 点击创建 API key 即可免费生成一个key值&#xff0c;别忘记保存。 第二步&#xff1a;找到deepseek官方接口文档 文档地址&#xff1a;https://api-docs.deepseek.com/zh-cn/ 第三步…...

算法19(力扣244)反转字符串

1、问题 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。 2、示例 &#xff08;1&#xff09; 示例 1&a…...

Svelte 最新中文文档翻译(10)—— use: 与 Actions

前言 Svelte&#xff0c;一个非常“有趣”、用起来“很爽”的前端框架。从 Svelte 诞生之初&#xff0c;就备受开发者的喜爱&#xff0c;根据统计&#xff0c;从 2019 年到 2024 年&#xff0c;连续 6 年一直是开发者最感兴趣的前端框架 No.1&#xff1a; Svelte 以其独特的编…...

iptables网络安全服务详细使用

iptables防火墙概念说明 开源的基于数据包过滤的网络安全策略控制工具。 centos6.9 --- 默认防火墙工具软件iptables centos7 --- 默认防火墙工具软件firewalld&#xff08;zone&#xff09; iptables主要工作在OSI七层的二、三、四层&#xff0c;如果重新编译内核&…...

node.js + html调用ChatGPTApi实现Ai网站demo(带源码)

文章目录 前言一、demo演示二、node.js 使用步骤1.引入库2.引入包 前端HTML调用接口和UI所有文件总结 前言 关注博主&#xff0c;学习每天一个小demo 今天是Ai对话网站 又到了每天一个小demo的时候咯&#xff0c;前面我写了多人实时对话demo、和视频转换demo&#xff0c;今天…...

Vue 3最新组件解析与实践指南:提升开发效率的利器

目录 引言 一、Vue 3核心组件特性解析 1. Composition API与组件逻辑复用 2. 内置组件与生命周期优化 3. 新一代UI组件库推荐 二、高级组件开发技巧 1. 插件化架构设计 2. 跨层级组件通信 三、性能优化实战 1. 惰性计算与缓存策略 2. 虚拟滚动与列表优化 3. Tree S…...

DeepSeek 助力 Vue 开发:打造丝滑的日期选择器(Date Picker),未使用第三方插件

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

kubernetes源码分析 kubelet

简介 从官方的架构图中很容易就能找到 kubelet 执行 kubelet -h 看到 kubelet 的功能介绍&#xff1a; kubelet 是每个 Node 节点上都运行的主要“节点代理”。使用如下的一个向 apiserver 注册 Node 节点&#xff1a;主机的 hostname&#xff1b;覆盖 host 的参数&#xff1…...