Linux13 传输层UDP和TCP协议

news2024/11/22 12:16:01

传输层UDP和TCP协议

  • 1. UDP 协议
    • 1.1 UDP协议端格式
    • 1.2 UDP特点
    • 1.3 UDP 的缓冲区
    • 1.4 UDP数据长度
    • 1.5 基于 UDP 的应用层协议
  • 2. TCP 协议
    • TCP协议端格式
    • 确认应答
      • 序号和确认序号位
      • 通信机制:
    • 超时重传
    • 连接管理
      • 三次握手 - 建立连接
      • 三次握手与TCPSocket
      • 问题 - 为什么要有三次握手
      • 四次挥手 - 断开连接
      • 问题 - TIME_WAIT状态
    • 流量控制
    • 滑动窗口
      • 概念
      • 丢包情况
    • 拥塞控制
      • 概念
      • 过程
      • 慢启动
    • 延迟应答
    • 捎带应答
  • 基于TCP应用层协议
  • 粘包问题
    • 描述
    • 解决方法
  • TCP、UDP对比
  • UDP实现可靠传输
  • 面向字节流

1. UDP 协议

1.1 UDP协议端格式

在这里插入图片描述

16位UDP长度,表示整个数据报(UDP首部 + UDP数据)的最大长度
如果校验和出错,直接丢弃

1.2 UDP特点

UDP 传输的过程类似于寄信

  • 无连接:知道对端的 IP 和端口号就直接进行传输, 不需要建立连接;(我只需要知道你的地址,就可以寄信给你)
  • 不可靠:没有确认机制, 没有重传机制; 如果因为网络故障该段无法发到对方,UDP 协议层也不会给应用层返回任何错误信息;(但我不能保证寄信的过程是否顺利)
  • 面向数据报:不能够灵活的控制读写数据的次数和数量
  • 应用层交给 UDP 多长的报文, UDP 原样发送, 既不会拆分, 也不会合并。
  • 如果发送端调用一次 sendto, 发送 100 个字节, 那么接收端也必须调用对应的一次 recvfrom, 接收 100 个字节; 而不能循环调用 10 次 recvfrom, 每次接收 10 个字节;

1.3 UDP 的缓冲区

  • UDP 没有真正意义上的 发送缓冲区. 调用 sendto 会直接交给内核, 由内核将数据传给网络层协议进行后续的传输动作;
  • UDP 具有接收缓冲区. 但是这个接收缓冲区不能保证收到的 UDP 报的顺序和发送 UDP 报的顺序一致; 如果缓冲区满了, 再到达的 UDP 数据就会被丢弃
  • UDP 的 socket 既能读, 也能写, 即全双工

1.4 UDP数据长度

  • UDP 协议首部中有一个 16 位的最大长度. 也就是说一个 UDP 能传输的数据最大长度是 64K(包含 UDP 首部)
  • 如果我们需要传输的数据超过 64K, 就需要在应用层手动的分包, 多次发送, 并在接收端手动拼装;

1.5 基于 UDP 的应用层协议

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

2. TCP 协议

TCP协议端格式

在这里插入图片描述

  1. 源端口号(16 位):标识发送方应用程序的端口号。不同的应用程序在发送数据时会使用不同的端口号,通过源端口号,接收方可以知道数据是从哪个应用程序发送过来的。
  2. 目的端口号(16 位):标识接收方应用程序的端口号。接收方的操作系统会根据目的端口号将数据传递给相应的应用程序。
  3. 序列号(32 位):用于对发送的数据进行编号。在 TCP 连接中,每个字节的数据都有一个唯一的序列号。序列号的初始值是随机生成的,后续的数据序列号是上一个数据的最后一个字节的序列号加 1。通过序列号,接收方可以对收到的数据进行排序和确认。
  4. 确认号(32 位):是接收方期望收到的下一个字节的序列号。当接收方成功接收到数据后,会向发送方发送一个确认报文,其中的确认号就是接收方期望收到的下一个字节的序列号。发送方根据确认号可以知道接收方已经接收到了哪些数据,从而决定是否需要重传。
  5. 数据偏移(4 位):也称为首部长度,以 4 字节为单位,表示 TCP 头部的长度。由于 TCP 头部的长度是可变的(选项字段的长度可变),所以需要这个字段来确定数据的起始位置。最小的 TCP 头部长度是 20 字节(5 个 4 字节),如果有选项字段,头部长度会增加。
  6. 保留位(6 位):为了以后的扩展而设置,目前一般被设置为 0。
  7. 标志位(6 位)
  • URG(紧急指针有效位):当该位为 1 时,表示紧急指针字段有效,说明当前数据中有紧急数据需要优先处理。
  • ACK(确认应答位):当该位为 1 时,表示确认号字段有效,确认应答机制是 TCP 实现可靠传输的核心机制之一。
  • PSH(推送位):当该位为 1 时,提示接收端应用程序立刻从 TCP 缓冲区把数据读走,而不是等到缓冲区满了再读取。
  • RST(复位位):当该位为 1 时,表示对方要求重新建立连接,一般在连接出现错误时使用。
  • SYN(同步位):在建立连接时使用,当该位为 1 时,表示请求建立连接,发送方会在建立连接的过程中发送带有 SYN 标志的报文。
  • FIN(结束位):当该位为 1 时,表示通知对方,本端要关闭连接了,发送方会在关闭连接时发送带有 FIN 标志的报文。
  1. 窗口大小(16 位):表示接收端期望通过单次确认而收到的数据的大小,即接收窗口的大小。通过窗口大小,发送方可以控制发送数据的速度,避免发送方发送的数据过多导致接收方缓冲区溢出。
  2. 校验和(16 位):用于检验 TCP 头部和数据部分的完整性。发送方在发送数据时会计算出一个校验和,并将其包含在 TCP 头部中。接收方在接收到数据后,也会计算校验和,并与接收到的校验和进行比较,如果不一致,则说明数据在传输过程中出现了错误。
  3. 紧急指针(16 位):只有在 URG 标志位为 1 时才有效,指出紧急数据在数据包中的偏移量,即紧急数据相对于当前数据的起始位置的偏移量。
  4. 选项(可变长度):是可选的字段,用于协商一些额外的功能或参数,如最大报文段长度(MSS)、窗口扩大因子等。选项的长度是可变的,因此需要数据偏移字段来确定选项的结束位置和数据的起始位置。
  5. 数据:是 TCP 传输的实际数据内容,其长度是可变的,但要受到窗口大小和网络 MTU(最大传输单元)的限制。

确认应答

  1. 要收到了应答,就能保证我们的数据,对方一定收到了(保证可靠性)
  2. 不对应答做应答

序号和确认序号位

  • 发送方在发送数据时,会为每一个字节的数据都进行编号,这个编号就是序列号(Sequence Number)
  • 接收方在成功接收到数据后,会向发送方返回一个确认应答报文,其中的确认号(Acknowledgment Number)是接收方期望收到的下一个字节的序列号。例如,发送方发送了序列号从 1 到 100 的数据,接收方成功接收后,返回的确认号就是 101,表示接收方期望下一次收到的是从序列号 101 开始的数据。
  • 确认应答的报文ACK标志位为1

通信机制:

  • 如果客户端发出1000,2000,3000,4000
  • 收到一个应答序号为3001,意思是3000之前的全部收到
  • 在网络传输过程中,由于不同的数据可能会经过不同的网络路径,导致到达接收方的顺序可能与发送方发送的顺序不同,即出现 “后发先至” 的情况。通过序列号和确认应答机制,接收方可以根据序列号对收到的数据进行排序,确保数据的正确顺序。即使数据乱序到达,接收方也可以根据序列号将其重新排序后再交给应用程序处理。

超时重传

  • 发送方发送数据后,会启动一个定时器等待接收方的确认应答。如果在定时器超时之前没有收到确认应答,发送方就会认为数据丢失或确认应答丢失,从而触发超时重传机制,重新发送该数据。
  • 随着重传次数的增加,超时时间会逐渐延长。例如在 Linux 系统中,超时时间以 500ms 为一个单位进行控制,每次判定超时重发的超时时间都是 500ms 的整数倍。如果重发一次之后仍然得不到应答,等待时间会变为 2 * 500ms 后再进行重传;如果还是得不到应答,就等待 4 * 500ms 进行重传,依次类推,以指数形式递增

连接管理

三次握手 - 建立连接

  • 第一次握手 - 客户端向服务器发送一个带有 SYN 标志位为 1 的报文,序列号假设为 x ,此时 ACK 标志位为 0,因为这是一个连接请求,还没有涉及确认应答。
  • 第二次握手 - 服务器收到客户端的 SYN 请求后,会发送一个带有 SYN 和 ACK 标志位都为 1 的报文。这个报文的 SYN 标志位为 1 是为了同步服务器自己的序列号(假设为 y,随机生成),ACK 标志位为 1 是为了确认收到客户端的连接请求,同时告知客户端下一个期望收到的序列号(确认号为 x + 1)。
  • 第三次握手 - 客户端收到服务器的 SYN - ACK 报文后,再发送一个 ACK 标志位为 1 的报文进行确认,确认号为 y + 1,此时连接正式建立,之后的数据传输阶段就按照正常的 ACK 置 1 的方式进行确认应答。

三次握手建立连接本质就是在赌最后客户端发给服务器的ACK一定收到

  • 如果最后一个包丢了怎么办?
  • 客户端在后续发送数据时,会收到来自服务器的RST(reset)标志位置一的报文
  • 表示服务器让客户端把原来的链接释放掉,重新三次握手(链接重置)

三次握手与TCPSocket

  • 根据之前的TCP套接字代码,客户端connect只是发起了三次握手
  • 三次握手完成,服务器accept就会返回文件描述符 —— accept不参与三次握手的过程,仅是等待三次握手完成
  • 三次握手是双方TCP协议层自主完成的

问题 - 为什么要有三次握手

  1. 验证全双工,验证网络连通性,用最小的次数验证自己能发能收
  2. 建立双方通信工时意愿,服务器发送了ACK时也发送了SYN(类似四次挥手)
  3. 协商双方的接受能力(与下面的流量控制有关)

四次挥手 - 断开连接

发起四次挥手的有可能是客户端,也有可能是服务器,以下描述仅针对客户端主动发起四次挥手。

  • 第一次挥手 - 客户端发送一个 TCP 首部中 FIN(Finish)标志位被置为 1 的报文,用来关闭本端到对端的数据传送。发送完后,**客户端进入 FIN_WAIT_1(终止等待 1)**状态,表示在等待对方的确认应答。
  • 第二次挥手 - 服务器收到 FIN 报文后,就向客户端发送一个 ACK 应答报文,确认序号为收到的序号加 1。此时服务器进入 CLOSE_WAIT(关闭等待)状态。在这个状态下,服务器会继续处理剩余的数据,准备关闭连接。而客户端收到 ACK 报文后,进入 FIN_WAIT_2(终止等待 2)状态,继续等待服务器的 FIN 报文。
  • 第三次挥手 - 当服务器处理完所有数据后,就会向客户端发送一个 FIN 报文,用来关闭服务器到客户端的数据传送。发送完后,服务器进入 LAST_ACK(最后确认)状态,等待客户端的最后确认。
  • 第四次挥手 - 客户端收到服务器的 FIN 报文后,回一个 ACK 应答报文,并将确认序号设置为收到的序号加 1。之后客户端进入 TIME_WAIT(时间等待)状态。经过 2 倍的最大报文段生存时间(2MSL)后,客户端自动进入 CLOSED状态,至此客户端完成连接的关闭。当服务器收到客户端的 ACK 报文后,也会进入 CLOSED状态,服务器方完成连接的关闭

总结:

  1. 客户端向服务器发送完数据了,跟服务器打个招呼
  2. 服务器确认收到,但不一定服务器也发完数据了,所以要等服务器把数据发完
  3. 服务器也发完数据了,通知一下客户端
  4. 客户端确认收到
    因此,四次挥手用最小的通信成本,建立了断开连接的共识(双方都不和对方通信了,且双方都知道对端不和自己通信了)
    四次挥手也是由双方操作系统自主完成(由close(fd))触发

问题 - TIME_WAIT状态

由四次挥手的过程可知:客户端主动断开连接,最后会进入先TIME_WAIT状态,这个状态为什么会等待2MSL?

  1. 这是TCP报文最大生成时间
  2. 必须等待此报文过了生存期自主消散,防止过期报文再次被收到
  3. 保证客户端发送的最后一个ACK报文段能够到达服务端
  • 这个ACK报文段有可能丢失,使得处于LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认,服务端超时重传FIN+ACK报文段,而客户端能在2MSL时间内收到这个重传的FIN+ACK报文段,接着客户端重传一次确认,重新启动2MSL计时器,最后客户端和服务端都进入到CLOSED状态,若客户端在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到服务端重传的FIN+ACK报文段,所以不会再发送一次确认报文段,则服务端无法正常进入到CLOSED状态。

流量控制

  • 客户端根据服务器发送确认应答报文的16位窗口大小控制流量(服务器也根据客户端发送的确认应答报文的16位窗口大小控制流量)。
  • 三次握手时,双方已经交换过了双方的接受能力;根据对方的接受能力,控制自身的发送数据的流量。
  • 一个主机没有接受能力,另一个主机会进行窗口探测

滑动窗口

  • 因为TCP有确认应答机制,对于每一个发送端的数据段,都要给一个ACK确认应答,收到ACK之后在发送下一个数据段,这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候。
  • 如果能一次发送多条数据, 就可以大大的提高性能(其实是将多个段的等待时间重叠在一起了)

概念

  • 滑动窗口大小指的是无需等待确认应答而可以继续发送数据的最大值,假设4000,每1000为一个段
  • 那么发送前四个段的时候, 不需要等待任何 ACK, 直接发送
  • 收到第一个 ACK 后, 滑动窗口向后移动, 继续发送第五个段的数据; 依次类推
  • 操作系统内核为了维护这个滑动窗口, 需要开辟 发送缓冲区 来记录当前还有哪些数据没有应答; 只有确认应答过的数据, 才能从缓冲区删掉
  • 窗口越大, 则网络的吞吐率就越高

丢包情况

  1. 数据包抵达了,对端发来的ACK丢了
  • 部分ACK丢了没关系,通过后续ACK进行确认
  1. 数据包丢了
  • 发0 - 4000,如果只有1000 - 2000报文段丢了,发送端会一直收到1001这样的ACK,当主机连续收到三次同样的ACK,就会进行重新发送。(快重传机制)
  • 接收端成功接收后,再次返回的就是4001,因为之前发送时这些已经被放到了接收端操作系统内核的接受缓冲区中

拥塞控制

概念

  • 虽然 TCP 有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题。
  • 因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起雪上加霜的.
  • TCP 引入 慢启动 机制, 先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据;

过程

  • 发送开始的时候, 定义拥塞窗口大小为 1;
  • 每次收到一个 ACK 应答, 拥塞窗口加 1;
  • 每次发送数据包的时候, 将拥塞窗口和接收端主机反馈的窗口大小做比较, 取较小的值作为实际发送的窗口
  • 即 滑动窗口大小 = min(拥塞窗口大小,应答窗口大小)

慢启动

  • 设置一个叫值做慢启动的阈值
  • 当拥塞窗口低于这个阈值的时候,按照指数方式增长
  • 当拥塞窗口超过这个阈值的时候, 不再按照指数方式增长, 而是按照线性方式增长

当 TCP 开始启动的时候, 慢启动阈值等于窗口最大值;
在每次超时重发的时候, 慢启动阈值会变成原来的一半, 同时拥塞窗口置回 1;
少量的丢包, 我们仅仅是触发超时重传; 大量的丢包, 我们就认为网络拥塞;
当 TCP 通信开始后, 网络吞吐量会逐渐上升; 随着网络发生拥堵, 吞吐量会立刻下降;

延迟应答

如果接收数据的主机立刻返回 ACK 应答, 这时候返回的窗口可能比较小
假设接收端缓冲区为 1M. 一次收到了 500K 的数据; 如果立刻应答, 返回的窗口就是 500K;
但实际上可能处理端处理的速度很快, 10ms 之内就把 500K 数据从缓冲区消费掉了;
在这种情况下, 接收端处理还远没有达到自己的极限, 即使窗口再放大一些, 也能处理过来;
如果接收端稍微等一会再应答, 比如等待 200ms 再应答, 那么这个时候返回的窗口大小就是 1M;

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

每隔N个包(2)应答一次,每隔200ms应答一次

捎带应答

捎带应答(Piggyback Acknowledgment)是 TCP 协议中为了提高传输效率而采用的一种机制。在正常的 TCP 通信中,接收方需要对发送方发送的数据进行确认,这个确认过程如果单独进行会产生额外的开销。捎带应答机制允许接收方在向发送方发送数据时,将确认应答信息一起发送,从而节省网络资源和传输时间。

  • 数据和确认的合并:假设客户端发送的数据序列号为 1 - 100,服务器收到后,在准备发送自己的数据(如服务器查询数据库后的结果)时,在 TCP 报文头部的确认号字段填入 101(表示已收到序列号 1 - 100 的数据,期望下一个收到的数据从序列号 101 开始),同时在报文的数据部分放入要发送给客户端的内容,如查询结果等信息。这样,一个 TCP 报文既包含了服务器发送的数据,又包含了对客户端数据的确认应答,实现了 “捎带” 的功能。
  • 总结:ACK和数据一起发过来

基于TCP应用层协议

  • HTTP
  • HTTPS
  • SSH
  • Telnet
  • FTP
  • SMTP

粘包问题

描述

  • 粘包问题中的 “包” , 是指的应用层的数据包
  • 在 TCP 的协议头中, 没有如同 UDP 一样的 “报文长度” 这样的字段, 但是有一个序号这样的字段.
  • 站在传输层的角度, TCP 是一个一个报文过来的. 按照序号排好序放在缓冲区中
  • 站在应用层的角度, 看到的只是一串连续的字节数据
  • 那么应用程序看到了这么一连串的字节数据, 就不知道从哪个部分开始到哪个部分, 是一个完整的应用层数据包
  • 对于 UDP, 如果还没有上层交付数据, UDP 的报文长度仍然在. 同时, UDP 是一个一个把数据交付给应用层. 就有很明确的数据边界
  • 站在应用层的站在应用层的角度, 使用 UDP 的时候, 要么收到完整的 UDP 报文, 要么不收. 不会出现"半个"的情况

解决方法

  • 对于定长的包, 保证每次都按固定大小读取即可; 例如上面的 Request 结构, 是固定大小的, 那么就从缓冲区从头开始按sizeof(Request)依次读取即可;
  • 对于变长的包, 可以在包头的位置, 约定一个包总长度的字段, 从而就知道了包的结束位置;
  • 对于变长的包, 还可以在包和包之间使用明确的分隔符(应用层协议, 是程序猿自己来定的, 只要保证分隔符不和正文冲突即可)

TCP、UDP对比

  • TCP 用于可靠传输的情况, 应用于文件传输, 重要状态更新等场景;
  • UDP 用于对高速传输和实时性要求较高的通信领域, 例如, 早期的 QQ, 视频传输等. 另外 UDP 可以用于广播;

UDP实现可靠传输

  • 引入序列号, 保证数据顺序;
  • 引入确认应答, 确保对端收到了数据;
  • 引入超时重传, 如果隔一段时间没有应答, 就重发数据
    …根据TCP的一些机制引入UDP

面向字节流

  • 创建一个 TCP 的 socket, 同时在内核中创建一个 发送缓冲区 和一个 接收缓冲区
  • 调用 write(send) 时, 数据会先写入发送缓冲区中;
  • 如果发送的字节数太长, 会被拆分成多个 TCP 的数据包发出;
  • 如果发送的字节数太短, 就会先在缓冲区里等待, 等到缓冲区里数据多起来, 或者其他合适的时机发送出去
  • 接收数据的时候, 数据也是从网卡驱动程序到达内核的接收缓冲区
  • 然后应用程序可以调用 read(recv) 从接收缓冲区拿数据;
  • 另一方面, TCP 的一个连接, 既有发送缓冲区, 也有接收缓冲区, 那么对于这一个连接, 既可以读数据, 也可以写数据. 这个概念叫做 全双工
  • 由于缓冲区的存在, TCP 程序的读和写不需要一一匹配
  • 写 100 个字节数据时, 可以调用一次 write 写 100 个字节, 也可以调用 100 次write, 每次写一个字节;
  • 读 100 个字节数据时, 也完全不需要考虑写的时候是怎么写的, 既可以一次read 100 个字节, 也可以一次 read 一个字节, 重复 100 次;

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

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

相关文章

Figure 02迎重大升级!!人形机器人独角兽[Figure AI]商业化加速

11月19日知名人形机器人独角兽公司【Figure AI】发布公司汽车巨头【宝马】最新合作进展,旗下人形机器人Figure 02在生产线上的性能得到了显著提升,机器人组成自主舰队,依托端到端技术,速度提高了400%,执行任务成功率提…

OpenCV 图片处理与绘制

目录 1. 图片处理 1.1 灰度处理 1.1.1 图像灰度化处理 1.1.2 图像灰度化的算法 1.2 图像二值化 1.3 边缘检测 ​编辑 2. 绘图 2.1 绘制线段 2.2 绘制矩形 2.3 绘制圆形 2.4 绘制椭圆 2.5 绘制多边形 2.6 绘制文字图片 1. 图片处理 1.1 灰度处理 将彩色图像转化为…

uniapp 城市选择插件

uniapp城市选择插件 如上图 地址 完整demo <template><view><city-selectcityClick"cityClick":formatName"formatName":activeCity"activeCity":hotCity"hotCity":obtainCitys"obtainCitys":isSearch&quo…

实验室资源调度系统:基于Spring Boot的创新

2相关技术 2.1 MYSQL数据库 MySQL是一个真正的多用户、多线程SQL数据库服务器。 是基于SQL的客户/服务器模式的关系数据库管理系统&#xff0c;它的有点有有功能强大、使用简单、管理方便、安全可靠性高、运行速度快、多线程、跨平台性、完全网络化、稳定性等&#xff0c;非常…

【Triton 教程】融合注意力 (Fused Attention)

Triton 是一种用于并行编程的语言和编译器。它旨在提供一个基于 Python 的编程环境&#xff0c;以高效编写自定义 DNN 计算内核&#xff0c;并能够在现代 GPU 硬件上以最大吞吐量运行。 更多 Triton 中文文档可访问 →https://triton.hyper.ai/ 这是根据 Tri Dao 的 Flash At…

近源渗透|HID ATTACK从0到1

前言 对于“近源渗透”这一术语&#xff0c;相信大家已经不再感到陌生。它涉及通过伪装、社会工程学等手段&#xff0c;实地侵入企业办公区域&#xff0c;利用内部潜在的攻击面——例如Wi-Fi网络、RFID门禁、暴露的有线网口、USB接口等——获取关键信息&#xff0c;并以隐蔽的…

大数据入门-什么是Flink

这里简单介绍Flink的概念、架构、特性等。至于比较详细的介绍&#xff0c;会单独针对这个组件进行详细介绍&#xff0c;可以关注博客后续阅读。 一、概念 Apache Flink 是一个框架和分布式处理引擎&#xff0c;用于在无边界和有边界数据流上进行有状态的计算。 Flink的四大基…

Excel如何批量导入图片

这篇文章将介绍在Excel中如何根据某列数据&#xff0c;批量的导入与之匹配的图片。 准备工作 如图&#xff0c;我们准备了一张员工信息表以及几张员工的照片 可以看到&#xff0c;照片名称是每个人的名字&#xff0c;与Excel表中的B列&#xff08;姓名&#xff09;对应 的卢易…

9个最佳WordPress PDF插件(查看器、嵌入和下载)

在过去的几年里&#xff0c;我们一直在使用不同的 PDF 插件在我们的网站上创建、编辑和嵌入文档。 然而&#xff0c;经过多次尝试和错误&#xff0c;我们意识到并不是每个插件都是相同的。事实上&#xff0c;为您的企业或电子商务网站选择合适的 PDF 插件可能是一项艰巨的任务…

java-贪心算法

1. 霍夫曼编码&#xff08;Huffman Coding&#xff09; 描述&#xff1a; 霍夫曼编码是一种使用变长编码表对数据进行编码的算法&#xff0c;由David A. Huffman在1952年发明。它是一种贪心算法&#xff0c;用于数据压缩。霍夫曼编码通过构建一个二叉树&#xff08;霍夫曼树&a…

Seatunnel运行时报错Caused by: java.lang.NoClassDefFoundError: com/mysql/cj/MysqlType

报错 [] 2024-11-21 16:46:27,526 ERROR org.apache.seatunnel.core.starter.SeaTunnel - Fatal Error, [] 2024-11-21 16:46:27,526 ERROR org.apache.seatunnel.core.starter.SeaTunnel - Please submit bug report in https://github.com/apache/seatunnel/issues[] 2024-11…

vue自定义指令--一键复制

vue项目中想要实现点击按钮一键复制&#xff0c;可以通过vue的自定义指令directive来实现。 一、新建directive.js文件 新建directive.js文件&#xff0c;用于定义所有的自定义指令。 import { Toast } from vant;const directive {// 一键复制copy:{bind (el, { value }) …

AI 大模型重塑软件开发的未来

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

python: generator model using sql server 2019

設計或生成好數據庫&#xff0c;可以生成自己設計好的框架項目 # encoding: utf-8 # 版权所有 &#xff1a;2024 ©涂聚文有限公司 # 许可信息查看 &#xff1a;言語成了邀功盡責的功臣&#xff0c;還需要行爲每日來值班嗎 # 描述&#xff1a; : 生成实体 # Author …

使用redis-shake工具进行redis的数据同步

前言&#xff1a; 工作中将常遇到测试环境和正式环境的数据同步或者需要进行数据迁移&#xff0c;对于mysql数据库的方案倒是不少&#xff0c;但是redis中如何快速便捷的迁移呢&#xff1f;答案是阿里云提供的:redis-shake RedisShake是阿里云基于豌豆荚开源的redis-port进行…

轻松实现文件远程传输:使用PicoShare搭建轻量级文件共享系统

文章目录 前言1. 本地安装Docker2. 本地部署PicoShare3. 如何使用PicoShare4. 公网远程访问本地 PicoShare4.1 内网穿透工具安装4.2 创建远程连接公网地址 5. 固定PicoShare公网地址 前言 什么是PicoShare&#xff1f; PicoShare 是一个由 Go 开发的轻量级开源共享文件系统。…

路由缓存后跳转到新路由时,上一路由中的tip信息框不销毁问题解决

上一路由tip信息框不销毁问题解决 路由缓存篇问题描述及截图解决思路关键代码 路由缓存篇 传送门 问题描述及截图 路由缓存后跳转新路由时&#xff0c;上一个路由的tip信息框没销毁。 解决思路 在全局路由守卫中获取DOM元素&#xff0c;通过css去控制 关键代码 修改文…

iOS 18.2 Beta 4开发者预览版发布,相机新增辅助功能

昨天刚连发iOS 18.1.1正式版、iOS 17.7.2正式版&#xff0c;今天凌晨&#xff0c;苹果就又发布iOS 18.2 Beta 4&#xff0c;据了解iOS18.2正式版将在 12 月初发布。那么这次的更新又有哪些变化呢&#xff1f;下面我们就来一起了解一下。 iOS 18.2 Beta 4的版本号为&#xff1a;…

PCB 间接雷击模拟

雷击是一种危险的静电放电事件&#xff0c;其中两个带电区域会瞬间释放高达 1 千兆焦耳的能量。雷击就像一个短暂而巨大的电流脉冲&#xff0c;会对建筑物和电子设备造成严重损坏。雷击可分为直接和间接两类&#xff0c;其中间接影响是由于感应能量耦合到靠近雷击位置的物体。间…

易语言学习-cnblog

易语言数据类型 数值转换命令&#xff08;自己学&#xff09; 数值到大写&#xff08;&#xff09;将一个数值转换到中文读法&#xff0c;第二个参数为是否为简体。 数值到大写&#xff08;123.44&#xff0c;假&#xff09; 猜测结果 数值到金额&#xff08;&#xff09;将双…