UDP_TCP
目录
- 1. 回顾端口号
- 2. UDP协议
- 2.1 理解报头
- 2.2 UDP的特点
- 2.3 UDP的缓冲区及注意事项
- 3. TCP协议
- 3.1 报头
- 3.2 流量控制
- 2.3 数据发送模式
- 3.4 捎带应答
- 3.5 URG && 紧急指针
- 3.6 PSH
- 3.7 RES
1. 回顾端口号
-
在 TCP/IP 协议中,用 “源IP”, “源端口号”, “目的IP”,“目的端口号”,“协议号” 这样一个五元组来标识一个通信(可以通过
netstat -n
查看)。 -
端口号范围划分:
-
0 - 1023:知名端口号,HTTP,FTP,SSH等这些广为使用的应用层协议,他们的端口号都是固定的。
ssh(22),ftp(21),telnet(23),http(80),https(443)
-
1024 - 65535:操作系统动态分配的端口号。客户端程序的端口号,就是由操作系统从这个范围分配的。
-
-
cat /etc/services
:看到知名端口号。 -
两个问题(详细见 网络基础(二)):
- 一个进程是否可以bind多个端口号? ------ 可以。
- 一个端口号是否可以被多个进程bind? ------ 不可以。
2. UDP协议
-
以UDP为例:当我们在客户端的应用层,通过 sendto 系统调用,将数据发送到服务端,站在网络协议栈的角度看待,该数据实际上是先被拷贝到传输层(传输层属于OS),而这部分数据就是 UDP 中看到的数据,应用层的报文经由传输层时,OS会封装一层传输层的报头,即 UDP 报头。
分装报头时,发送端会随机形成一个源端口,并填充目的端口号。其中的 UDP 长度代表的是整个 UDP 报文的长度,检验和则是检验整个报文在传输过程中是否出错。
因此,我们过去在 udp_socket 编程时,客户端需要在发送请求的同时,填充服务端的端口号,以及定义端口号时,我们采用的类型是 uint16_t,这一切都是源于 UDP 的报头决定的!
-
而因为网络通信时,报文在协议栈中自顶向下是要分装的,最后再自底向上解包分用。因此,我们需要解决
- 报头和有效载荷的分离问题:固定报头长度。
- 有效载荷是如何向上交付的问题:绑定目的端口号。
- UDP 是面向数据报的,如何保证接收到的报文是完整的? ------ 通过报头长度确定,如果报头长度小于8字节,报头都有问题,整个报文直接丢弃;大于8字节,UDP长度 - 报头长度 = 数据长度。
2.1 理解报头
-
我们在各种教科书上看到的报头都形如上图,但是报头究竟是个什么东西呢?
一个描述报头的结构体,所谓报头,就是一个结构化的数据。
struct udphdr {uint16_t src_port, dst_port;uint16_t udp_len, checksum; }
但是,一个服务器是同时对接多个客户端的,因此服务器内是会存在大量的报文的,因此操作系统内可能积攒大量的报文,可能还没有向应用层进行交付,那么操作系统就需要对这些 UDP/TCP 报文管理起来。
内核中存在一个 sk_buff 结构体,其中有 *data、*tail 两个字段的指针(指向同一位置),并且在内核中定义一段缓冲区,用户保存接收到的报文数据。假设应用层通过 sendto 将 “hello” 发送到传输层,那么在拷贝到传输层时,*data 指针就向前移动 5 个字节,用于存储上层发送的数据。接着,还需要定义一个 udphdr 报头对象,*data 指针继续向前偏移 8 个字节,用于存储报头数据。这就是 UDP 封装。
而 UDP 层可能积攒了很多的报文数据,只需要通过
struct sk_buff *next
字段,将报文以链表的形式组织起来。这样一来,对报文的管理,就转变为对链表的增删查改。 -
更重要的是,不同端的主机通信,采用的也是网络协议栈,同样也有传输层。什么是协议?双方都需要按照同样的规则、同样的标准来通信。因此,在不同端,无论收发信息,采用的都是 udphdr 这样的描述结构体,双方使用同样的数据类型来解释收到的 UDP 报头的 8 个字节。因此协议就是结构化数据,协议就是一种约定。
2.2 UDP的特点
-
无连接:知道对端的 IP 和端口号就直接进行传输,不需要建立连接。
-
不可靠:没有确认机制,没有重传机制;如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息。
-
面向数据报:不能够灵活的控制读写数据的次数和数量(在向上层交付时,UDP 清楚的报文的有效载荷是多少个字节)。
应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并。
例如:用UDP传输100个字节的数据,如果发送端调用一次 sendto,发送100个字节,那么接收端也必须调用对应的一次 recvfrom,接收100个字节,而不能循环调用10次 recvfrom,每次接收10个字节。
-
UDP的 socket 既能读,也能写,这个概念叫做全双工。
2.3 UDP的缓冲区及注意事项
-
UDP没有真正意义上的发送缓冲区,调用 sendto 会直接交给内核,由内核将数据传给网络层协议进行后续的传输动作。
-
UDP具有接收缓冲区,但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致(即可能先发的后收到)。如果缓冲区满了,再到达的UDP数据就会被丢弃。
-
我们注意到,UDP 协议首部中有一个16位的最大长度,也就是说一个 UDP 能传输的数据最大长度是64K(包含UDP首部)。 然而 64K 在当今的互联网环境下,是一个非常小的数字,如果我们需要传输的数据超过64K,就需要在应用层手动的分包,然后多次发送,并在接收端手动拼接。
3. TCP协议
3.1 报头
-
同样的,TCP 报头在内核中也是一种结构化的字段。
-
4 位首部长度:取值范围 [ 0000 , 1111 ] = [ 0 , 15 ] [0000,1111] = [0, 15] [0000,1111]=[0,15],单位是 4个字节,即 4 位首部长度实际的取值范围为 [ 0 , 15 ] ∗ 4 = [ 0 , 60 ] [0, 15] * 4 = [0,60] [0,15]∗4=[0,60],也就意味着选项字段的大小,最多为 40 40 40 字节。
假设 TCP 报头的长度为 20 20 20 字节,那么首部长度即为 x ∗ 4 = 20 x * 4 = 20 x∗4=20, x = 5 x = 5 x=5 ,即 x = 0101 x = 0101 x=0101;
有了首部长度 x x x,默认先读取前 20 20 20 字节,提取首部长度字段,如果 x = 20 x = 20 x=20,即代表报头为 20 20 20 字节;如果 x > 20 x > 20 x>20, x − 20 = x - 20 = x−20= 选项字段长度,剩下的就是数据长度。这样一来,即解决了报头和有效载荷的分离问题。
与 UDP 协议同理,当应用层将数据通过 sendto 传递给传输层后,传输层申请 sk_buff 缓冲区,接着将数据从用户空间拷贝到 sk_buff 缓冲区,再为 TCP 报文构建协议报头并填充字段,最后将报头添加到 sk_buff 缓冲区中。至此,完成对 TCP 报文的封装。
-
6位标志位(后面详讲):
- URG: 紧急指针是否有效
- ACK:确认号是否有效(即应答报文设置的标志位)
- PSH:提示接收端应用程序立刻从 TCP 缓冲区把数据读走
- RST:对方要求重新建立连接,我们把携带 RST 标识的称为复位报文段
- SYN:请求建立连接,我们把携带 SYN标识的称为同步报文段(用于三次握手建立连接)
- FIN:通知对方,本端要关闭了,我们称携带 FIN 标识的为结束报文段(四次挥手关闭连接)
3.2 流量控制
- 与 UDP 不同的是,TCP 拥有独立的 发送和接收 缓冲区。并且,单独的客户端既可以同时发送和接收,因此 TCP 是全双工通信。
-
假设 TCP 通信的双方,一方发的特别快,另一方处理数据比较慢,但是发送方仍一直持续的发送,那么接收缓冲区就会被写满。但是发送方对于接收缓冲区已经被写满并不知情,所以继续在发送数据,但是数据又存不下了,于是报文被直接丢弃了?
丢弃后,虽然 TCP 后续可能对该报文进行重传。但是,可能这份报文可能经过无数个路由器,转发了无数次报文,好不容易到才到达目的地,花费这么大的代价,结果被丢弃了??这种做法是不合理的!
面对上述情况,本质问题就是,发送方无法得知接收方缓冲区的情况。如果接受方来不及接收报文了,发送方 放缓 或 暂停发送,问题就能够得到解决,而这种解决方法称为 流量控制。
在实际 tcp_socket 通信时,我们并没有遇到这类问题,因为上面的工作,已经由发送方的 TCP 完成了,用户并不需要关心,由 TCP 全权负责,这也是为什么 TCP 称为 传输控制协议!在实际的网络通信中,用户层调用 sendto 将数据传递到传输层后,在上层,我们就认为数据已经发送出去了,而实际上,可能数据还存储在本地操作系统的缓冲区内,还未进行发送。
-
TCP 为了保证传输的可靠性,协议要求 TCP 的接收方必须在收到报文后进行确认(向客户端进行响应反馈), 即 确认应答机制。
需要注意的是,假设发送的数据为 " h e l l o " "hello" "hello",真正发送的时候,可不仅仅只有数据,而是将数据封装在报文内,将整个 TCP 报文发送给对方。同样的,接收方在给发送方进行应答时,也是发送的一个 TCP 报文,同时在报头中设置了 ACK 标志位(ACK标志位置 1 1 1)。
-
16 位窗口大小: 记录发送方接收缓冲区的剩余空间大小。
-
那么如何进行流量控制呢?? ------ 发送方能够得知接收方的接收能力。
而接收缓冲区接收能力的强弱,以剩余的空间大小为衡量。因此当接收方在向发送方进行应答时,在应答的报头中的 窗口大小字段,填充自己接收缓冲区的剩余空间大小,那么发送方就能够清楚的进行传输控制了!
即,窗口大小是用于流量控制的字段!
上述一切关于流量控制的方式、细节,全部由 TCP 通信的双方的操作系统协商完成!
-
当接收缓冲区被写满,发送方也就停止发送,但是上层用户可不关心!上层用户还是继续向传输层写写写,那当发送缓冲区也被写满了呢??
这就是典型的生产消费模型,消费者不消费了,生产者就进行要阻塞!即进程就要进入阻塞状态,其本质就是进程在等待 OS 进行发送。进程是一个执行流,OS 也是一个执行流,这就是两个执行流在进行同步!
-
即便 TCP 是传输具有可靠性的,但也无法保证 100% 可靠的网络通信。
假设 C 端给 S 端发送第一条信息,但是在这条信息发送出去,到 S 端进行应答之前这段时间,对于 C 端,它是无法确认这次的报文对方是否收到。
当 S 端给 C 端应答第一条信息后,那么就轮到 S 端无法确认它发出去的报文对方是否收到。那如果要做到 S 端也能够确认自己的报文对方收到了,那就需要 C 端继续发送一次应答,那这次应答的报文,对于 C 端,它又无法确认对方是否收到(因为还没收到对方的应答)。
所以这个是一个死循环,永远无法确认最新的一条信息对方是否收到了,也即最新的一条消息的可靠性其实是无法保证的。但是!可以保证除了最后一条信息之前的所有信息的可靠性,如上图所示,① 和 ② 都是收到了应答,因此除了最新的 ③ 信息,其它都能够保证可靠性。
2.3 数据发送模式
-
像我们上面介绍的通信方式,C 端给 S 端发送数据, S 端需要给 C 端进行应答,反之同理。这些都是串行发送的,通信效率比较慢。
这是 TCP 发送数据常见的方式,将发送时间进行重叠,并发的发送多份报文,并且规定每个报文都需要进行应答,保证可靠性的同时提高效率。
-
由于网络的实际情况错综复杂,因此无法保证接收顺序与发送顺序一致,那么就可能导致数据乱序的问题(可能一份数据拆分为多个报文进行发送),而乱序是不可靠的一种表现,因此在同时发送多份报文的情况下,需要保证报文按序到达。
即报头内的 32 位序号:给报文携带编号。接收方可以根据报头中序号,对接收到的报文进行排序,即可保证报文按序到达。
-
还有一个问题是:C 端发了 4 份报文,S 端是需要给 C 端应答 4 次的,那么 S 端的哪一次应答是对 C 端的哪一次报文做的应答呢???如果不能解决这个问题,那么当发送方发了 10 个报文,最终只收到了 9 个应答,那发送方就无法得知,自己发送的 10 个报文里面,到底是哪个报文丢了!导致也无法进行后续补发报文的操作。
因此报头中还有另一个字段 ----- 32位确认序号:用于记录历史上发送方发送的哪些报文已经被接收方所接收,由接收方在应答报头中填充,对应收到报文的序号值 + 1。
确认序号之前的所有报文已经被接收方收到。例如:确认序号301代表的含义是序号300 200 100 的报文都已经被 S 端收到了。之所以这样设计的原因是:不管是数据还是应答,在网络传输中都有可能丢失,假设 S 端前三次报文都收到了,但是这三次应答都丢失了,最后一份报文的应答 401 没有丢失,那么 C 端在接收到 S 端的 401 应答时,即可以得知 4 份报文, S 端都接收到了。换言之,这样设计,可以允许少量的应答丢失。
3.4 捎带应答
-
看似一切完美,在应答的时候明明可以继续用 32 位序号来保障应答的可靠性,为啥还要多设计出一个32位确认序号呢??
要清楚,我们至始至终,为了方便理解,一直都是以单向通信为例。但实际上的通信是双向的,即 C 端 在向 S 端发数据的同时, S 端 也在给 C 端发数据。
那么 S 端 就需要在应答 C 端的同时,发送自己的数据。如果只有一个 32 位序号,那么应答 和 发数据 这两件事就需要分开来完成,即 S 端需要向 C 端发送两次报文。而有了 32 位确认序号后,这两件事可以同时完成,即发送数据的同时顺带给 C 端应答了!这就叫做捎带应答!!
实际通信时,大部分报文都既是数据,又是对历史报文的应答确认!
总结:TCP 在保证可靠性的同时,还会进行各种提高效率的设定(数据并发发送、捎带应答)!只不过这些工作都有 TCP(内核) 自主完成,用户并不知情。
3.5 URG && 紧急指针
-
标志位:用于标识不同的报文类型。
服务器是同时面对多个客户端的,即需要同时处理来自多个客户端的 TCP 报文,而这些报文可能包含连接建立、连接断开、正常数据传输或异常数据等类型。那么服务器就必须具备识别不同报文类型的能力,才能根据报文类型执行相应的处理动作。
-
我们上面说过,发送方可能同时一次性发送一批报文,并且这批报文的数据是有顺序的,那么就必须保证这批报文按序到达,而按序到达的本质就是队列(先发先收)。但不妨有时候会有一些紧急任务,那么在按序到达的规则下,即便是紧急任务,也要排队!但所谓紧急任务,肯定是需要尽快处理、提前被处理的。
因此面对这种情况,URG 标志位置 1,表明该报文是紧急报文。
-
16位紧急指针:记录紧急数据在有效载荷中的偏移量。
收到报文,先查看标志位,如果 U R G = 1 URG = 1 URG=1,那么根据紧急指针查看紧急数据(紧急数据只有一个字节)。
紧急任务的场景:假设发送方上传一批数据,但是上传过程中发现上传错了,而此时接收方的缓冲区已经积攒了大量的报文还没被处理,这种情况就可以发送紧急指针,示意对方立即终止或暂停上传行为(通过一些固定的标志信息反馈)(如果直接关闭连接,那么接收方需要把缓冲区的数据全部读取完,才能得知发送方已经关闭连接)。
再者,例如当发现服务器运行速度比较慢时,通过给服务器发送紧急指针,进行服务检测。
-
在发送 send 和 接收 recv 的第三个参数 flag,就会提供一些标志位,例如 MSG_OOB 就表示紧急数据。
ssize_t recv(int sockfd, void *buf, size_t len, int flags);MSG_OOBThis flag requests receipt of out-of-band data that would not be received in the normal data stream.
3.6 PSH
-
在讲流量控制的时候,我们讲过,当接受发给发送方应答的同时,报头中的窗口大小会记录接收方缓冲区剩余空间大小,以便发送方进行传输控制。
假设接收方上层 http 处理数据比较耗时,导致接收缓冲区被写满,随后接收方在应答报文中将窗口大小设置为 0,告知对方无法接收更多数据。一段时间后,接收方的上层处理了一些数据,缓冲区腾出一些空间,但此时的发送方并不知情,还在傻傻的阻塞等待。
因此,为了避免这种情况,发送方会定期发送空闲时间较长的询问报文(这种方式效率较低,因为它依赖超时来触发询问),然后等待接收方的应答。另一方面,当接收方的缓冲区的剩余空间由 0 0 0 变为 ! 0 !0 !0 时,接收方也会主动向发送方进行窗口大小的更新报文。
-
这里所谓的询问报文,也是完整的 TCP 报头,同时将 PSH 标志位置 1。即 PSH:告知对方,尽快将数据向上层交付。
但 PSH 不仅仅应用于询问报文中,当数据需要被尽快交付时,也可以使用。最典型的案例就是,xshell 远程连接远端服务器时,为了保证更好的用户体验,xshell 尽可能的让用户输入的每一条指令携带 PSH 标志位,让上层的 ssh 尽快交付解释。
3.7 RES
-
我们一直在说通信,但建立 TCP 通信的前提是建立连接,而建立连接就需要三次握手。
虽然 TCP 是保证可靠性的,但不代表三次握手就必须是成功的,也可能是失败的!保证的不是数据 100% 到达目的地,而是数据到达目的地了 或者 数据传输异常了,TCP 需要知道。
-
三个报文的前两个报文丢失都不影响,假设客户端连接建立请求的报文丢失了,服务端没有收到(服务端知情),那么也就不会给应答。客户端收不到服务端的应答,也就同样知情报文丢了(要么是自己的,要么是对方的应答报文),那么客户端就会进行报文重发。而假设服务端的报文丢了,虽然服务端自己不知情,但是客户端没收到,客户端是知情的,它就不会给服务端发送应答报文,那么服务端收不到应答报文,服务端也知情了。
最麻烦的是最后一次 ACK,假设最后一次客户端的 ACK 丢了,但客户端并不知情。站在客户端的角度,客户端认为,最后一次 ACK 报文发送出去即连接建立成功,而服务端需要等到接收了报文才认为连接建立成功。这种情况就会导致双端连接建立认知不一致的问题。
因为客户端认为连接建立好了,所以它就开始向服务端发送数据,服务端收到数据后,脑袋大大的问号,因为它认为三次握手还没完成,于是服务端就向客户端推送一个报文,并在报头中设置 RST 标志位。客户端收到 RST 标志位的报文后,就重置连接,重新开始三次握手。
-
因此,三次握手的最后一次,是无法保证可靠性的,即三次握手不是一定成功的,但可以通过 RST 标志位做容错处理。
同样的, RST 也不仅仅应用于三次握手。例如当双方通信的过程中,客户端网络中断,连接被释放了。随后客户端恢复了网络环境,但服务端并不知道,于是继续向客户端发送数据。这也是双端连接建立认知不一致的情况。客户端恢复网络后,它认为连接还没建立,但服务器不知情,依旧认为连接还在。这种情况,客户端同样可以向服务器发送 RST 重置连接请求。
相关文章:

UDP_TCP
目录 1. 回顾端口号2. UDP协议2.1 理解报头2.2 UDP的特点2.3 UDP的缓冲区及注意事项 3. TCP协议3.1 报头3.2 流量控制2.3 数据发送模式3.4 捎带应答3.5 URG && 紧急指针3.6 PSH3.7 RES 1. 回顾端口号 在 TCP/IP 协议中,用 “源IP”, “源端口号”…...

Python 中常见的数据结构之二推导式
Python 中常见的数据结构之二推导式 使用推异式列表推导式字典推导式集合推导式 使用推异式 推导式是一种从已存在的序列中快速构建列表(list)、集合(set) 和 字典(dictionary)方式。Python 支持 3 种不同类型的推导式: 列表推导式;字典推导式…...

STM32 拓展 低功耗案例3:待机模式 (hal)
配置PA0的两种方式: 第一种 第二种 复制寄存器代码然后对其进行修改 mian.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body…...

【开源社区openEuler实践】探索 Yocto-Meta-OpenEuler:嵌入式开发的强大基石
title: 探索 Yocto-Meta-OpenEuler:嵌入式开发的强大基石 date: ‘2024-11-19’ category: blog tags: Yocto-Meta-OpenEuler嵌入式系统开源项目定制化开发 sig: EmbeddedTech archives: ‘2024-12’ author:way_back summary: Yocto-Meta-OpenEuler 为嵌入式系统开…...

C++ hashtable
文章目录 1. 基本概念2. 哈希函数3. 哈希冲突及解决方法开放定址法链地址法再哈希法建立公共溢出区4. 哈希表的操作实现5. 内存管理及优化 时间复杂度理想情况(无哈希冲突或冲突极少)一般情况(考虑哈希冲突及解决方法)综合来看 以…...

JS (node) 的 ACM 模式 + debug方法 (01背包为例)
文章目录 JS 的 ACM 模式输入处理 JS dubug (01背包为例)动态输入在本地通过 Node.js 运行和调试 硬编码 Hard CodingVS Code JS 的 ACM 模式 在 JavaScript 中,ACM 模式一般通过 Node.js 的 readline 模块实现。 输入处理 使用 readline 模块监听输入。 将每行输…...

vue设计与实现-框架设计
权衡的艺术 命令式和声明式 视图层框架通常分为命令式和声明式,各有优缺。jquery是一种命令式框架。命令式框架关注过程,而声明式框架关注结果。对于vue来说,过程被vue封装了,所以vue内部是命令式的,但vue暴露给用户…...

Stable Diffusion和Midjourney有什么区别?
Stable Diffusion 和 Midjourney 主要有以下区别: 目录 费用与可访问性 设备要求 安装与使用 学习成本 图像生成效果 可控性与定制性 私密性 费用与可访问性 Stable Diffusion:开源免费,任何人都可以免费下载并自行部署使用…...

即插即用,无痛增强模型生成美感!字节跳动提出VMix:细粒度美学控制,光影、色彩全搞定
文章链接:https://arxiv.org/pdf/2412.20800 代码地址:https://github.com/fenfenfenfan/VMix 项目地址:https://vmix-diffusion.github.io/VMix/ 亮点直击 分析并探索现有模型在光影、色彩等细粒度美学维度上生成图像的差异,提出…...

面向对象分析和设计OOA/D,UML,GRASP
目录 什么是分析和设计? 什么是面向对象的分析和设计? 迭代开发 UML 用例图 交互图 基于职责驱动设计 GRASP 常见设计原则 什么是分析和设计? 分析,强调是对问题和需求的调查研究,不是解决方案。例如&#x…...

【每日学点鸿蒙知识】广告ID、NFC手机充值、CSS支持语法、PC与模拟器交互、SO热更新等
1、HamonyOS 样机获取成功返回Oaid为00000000-0000-0000-0000-000000000000? 请求授权时需要触发动态授权弹窗,看一下是不是没有触发授权弹窗。 可以参考以下代码以及文档: // ets import identifier from ohos.identifier.oaid; import hilog from oh…...

30分钟学会HTML
HTML 基本语法 HTML(HyperText Markup Language)是构成网页内容的基础。它使用一系列的标签来描述网页的结构,包括文本、图片、链接等元素。浏览器会解析这些标签并渲染成我们看到的网页。 在线体验一下 CodePen (在线 HTML 编辑器)。 千万不…...

服务器信息整理:用途、操作系统安装日期、设备序列化、IP、MAC地址、BIOS时间、系统
文章目录 引言I BIOS时间Windows查看BIOS版本安装日期linux查看BIOS时间II 操作系统安装日期LinuxWindowsIII MAC 地址IV 设备序列号Linux 查看主板信息知识扩展Linux常用命令引言 信息内容:重点信息:用途、操作系统安装日期、设备序列化、IP、MAC地址、BIOS时间、系统 Linux…...

Golang设计模式目录
go语言实现设计模式 1 文章目录: 1.1 创建型模式 1.Golang设计模式之工厂模式2.Golang设计模式之抽象工厂模式3.Golang设计模式之单例模式4.Golang设计模式之建造者模式5.Golang设计模式之原型模式 1.2 结构型模式 6.Golang设计模式之适配器模式7.Golang设计模式之桥…...

选择IT驻场外包公司,要找有哪些资质的公司
在当今数字化快速发展的时代,IT驻场外包服务成为众多企业优化运营、提升竞争力的关键选择。无论是初创企业寻求技术起步支持,还是大型企业为降低成本、专注核心业务而将部分 IT 职能外包,IT 外包公司都扮演着至关重要的角色。然而,…...

Java List 集合详解:基础用法、常见实现类与高频面试题解析
正文 在 Java 集合框架中,List 是一个非常重要的接口,广泛用于存储有序的元素集合。本文将带你深入了解 List 接口的基本用法、常见实现类及其扩展,同时通过实际代码示例帮助你快速掌握这些知识。 👉点击获取2024Java学习资料 1…...

Arduino UNO 驱动1.8 TFT屏幕显示中文
背景 最近入手了一块1.8寸的tft屏幕,通过学习文档,已经掌握了接线,显示英文、数字、矩形区域、划线、画点等操作, 但是想显示中文的时候操作比较复杂。 问题 1、arduino uno 驱动这款屏幕目前使的是自带的<TFT.h> 库操作…...

Flink operator实现自动扩缩容
官网文档位置: 1.Autoscaler | Apache Flink Kubernetes Operator 2.Configuration | Apache Flink Kubernetes Operator 1.部署K8S集群 可参照我之前的文章k8s集群搭建 2.Helm安装Flink-Operator helm repo add flink-operator-repo https://downloads.apach…...

分布式系统架构6:链路追踪
这是小卷对分布式系统架构学习的第6篇文章,关于链路追踪,之前写过traceId的相关内容:https://juejin.cn/post/7135611432808218661,不过之前写的太浅了,且不成系统,只是简单的理解,今天来捋一下…...

vite-plugin-imagemin安装问题
vite-plugin-imagemin 是一款图片资源压缩插件,能够在打包的时候显著的降低图片资源占用。不过,在安装过程中我们遇到了如下的问题。 对于上面的问题,有以下几种常见的解决方案: 1,使用 yarn 在 package.json 内配置(推荐) 打开 package.json 配置文件,然后添加如下脚本…...

Git revert回滚
回退中间的某次提交(此操作在预生产分支上比较常见),建议此方式使用命令进行操作(做好注释,方便后续上线可以找到这个操作) Git操作: 命令:revert -n 版本号 1:git re…...

永磁同步电机预测模型控制(MPC)
永磁同步电机预测模型控制(MPC) 文章目录 前言1、模型预测控制1.1 连续控制集模型预测控制(CCS-MPC)1.2 有限控制集模型预测控制(FCS-MPC)1.3 模型预测控制的优缺点 2、永磁同步电机模型预测控制2.1 预测模型2.2 价值…...

【JAVA】switch ... case ... 的用法
语法结构: switch(表达式){ case 值1: 表达式和值1匹配时执行的语句 break; case 值2: 表达式和值2匹配时执行的语句 break; …...

基于STM32的热带鱼缸控制系统的设计
文章目录 一、热带鱼缸控制系统1.题目要求2.思路3.电路仿真3.1 未仿真3.2 开始仿真,显示屏显示水温、浑浊度、光照强度等值3.3 当水温低于阈值,开启加热并声光报警3.4 当浑浊度高于阈值,开启自动换水并声光报警3.5 当光照低于阈值,…...

Vue项目整合与优化
前几篇文章,我们讲述了 Vue 项目构建的整体流程,从无到有的实现了单页和多页应用的功能配置,但在实现的过程中不乏一些可以整合的功能点及可行性的优化方案,就像大楼造完需要进行最后的项目验收改进一样,有待我们进一步…...

WinForm开发-自定义组件-1. 工具栏: UcompToolStrip
这里写自定义目录标题 1. 工具栏: UcompToolStrip1.1 展示效果1.2 代码UcompToolStrip.csUcompToolStrip.Designer.cs 1. 工具栏: UcompToolStrip 自定义一些Winform组件 1.1 展示效果 1)使用效果 2)控件事件 1.2 代码 设计 编码 UcompToolStrip.…...

法律专业legal case的留学论文写作技巧分析(1)
对于法律专业的留学生而言,案例的分析是写作的重要方面。无论留学的国家是英、美、澳洲还是加拿大,它们都属于case law 的法律体系。一个非常显著的特点便是通过对案例进行分析和提炼,从中总结提炼出principle和rules。case analysis的留学论…...

2025编程技术前沿:探索最新的开发工具与趋势
随着技术的飞速发展,编程领域每天都在演化,新的技术、框架和工具层出不穷。本文将聚焦2025年最具潜力和吸引力的编程技术与工具,从前沿语言到最受欢迎的开发框架,带您一起探索软件开发领域的最新趋势。 一、编程语言的新生代之星…...

sqlserver sql转HTMM邮件发送
通过sql的形式,把表内数据通过邮件的形式发送出去 declare title varchar(100) DECLARE stat_date CHAR(10),create_time datetime SET stat_dateCONVERT(char(10),GETDATE(),120) SET create_timeDATEADD(MINUTE,-20,GETDATE()) DECLARE xml NVARCHAR (max) DECLAR…...

GeoTrust True BusinessID Wildcard
GeoTrust由DigiCert 提供支持,是最受信任和尊重的品牌之一,以提供高保证的网站安全而闻名。 GeoTrust True BusinessID通配符证书 – 以低成本保护多个主机名。即使将其用于您的公司主页或电子邮件服务器主机名,保护所有敏感信息也是您的目标…...