Java网络模型全扫盲

概述

讲述ava层面NIO基础知识,用作基础回顾所用

1. NIO概述

​ 在Java中,NIO(Non-blocking I/O 或 New I/O)是Java SE 1.4及后续版本中引入的一套新的输入/输出操作API。

​ 它与传统的IO模型相比,提供了更高的效率和更好的并发处理能力。NIO的关键特性在于它的非阻塞特性,这使得单个线程能够管理多个I/O通道,从而极大地提高了在高并发场景下的应用性能。

​ Java NIO的使用场景特别适合于需要处理大量并发连接的情况,例如在网络服务器中,一个线程可以管理成千上万个客户端连接,而不需要为每一个连接分配一个独立的线程,这样可以显著降低系统的资源消耗和提高处理能力

2. Java中NIO三大组件

1. Channels(通道)

​ 通道是Java NIO中数据流的媒介,它是双向的,既可以用来读取数据,也可以用来写入数据。通道的主要优点在于它们是非阻塞的,这意味着一个线程可以管理多个通道,当某个通道上没有事件发生时,线程不会被阻塞,而是可以去处理其他任务。主要的通道类型包括:

  • FileChannel:用于文件的读写操作,可以用于将数据从缓冲区写入文件,或将数据从文件读入缓冲区。
  • SocketChannel:用于网络通信中的TCP连接,可以用来读写数据。
  • ServerSocketChannel:用于接受新的SocketChannel连接,类似于传统的ServerSocket。
  • DatagramChannel:用于UDP通信,可以发送和接收数据报。

2. Buffers(缓冲区)

​ 缓冲区是NIO中用于存储数据的对象,它是一个可以写入数据,也可以从中读取数据的字节数组。缓冲区有特定的容量(capacity),并且具有两个重要的属性:位置(position)和限制(limit)。

  • 容量(Capacity):缓冲区可以存储的最大元素数。
  • 位置(Position):当前正在操作的元素的索引,读取或写入数据时会改变。
  • 限制(Limit):读取模式下,位置可以达到的最大值;写入模式下,位置不能超过的值。

缓冲区的主要类型有ByteBufferCharBufferShortBufferIntBufferLongBufferFloatBufferDoubleBuffer,每种类型对应一种原始数据类型。

3. Selectors(选择器)

​ 选择器是NIO中的多路复用器,它允许一个单独的线程监控多个通道的事件,如读、写、连接和接收事件。当其中一个通道准备好进行I/O操作时,选择器会通知应用程序。选择器的使用极大地提高了网络应用程序的并发处理能力,因为不需要为每个连接创建一个线程。

选择器的主要方法包括:

  • select():阻塞直到至少有一个通道准备好I/O操作。
  • selectedKeys():返回一个Set,其中包含所有准备好的通道的SelectionKey对象。
  • wakeup():中断阻塞的select()调用。

SelectionKey是选择器和通道之间的关联,它代表了一个通道在选择器上的注册状态,包括通道、选择器、感兴趣的事件集合和已就绪的事件集合。

3. 网络编程

1. 阻塞I/O (Blocking I/O)

​ 这是最传统的I/O模型,在Java中,传统的Socket和ServerSocket API都是基于阻塞I/O的。在这种模式下,当线程发起一个读或写操作时,该线程会被阻塞,直到I/O操作完成。如果读操作没有数据可读,或者写操作无法立即完成,线程就会一直等待,直到操作完成。

特点:

  • 简单的编程模型:易于理解和实现。
  • 资源占用:每个连接都需要一个独立的线程,导致线程数量受限,资源消耗大。
  • 性能限制:高并发场景下,线程切换和上下文切换开销大,容易成为瓶颈。

2. 非阻塞I/O (Non-Blocking I/O)

​ 非阻塞I/O是Java NIO (New I/O)框架的一部分,允许线程在发起读写操作时不会被阻塞。如果一个读操作没有数据可读,或者写操作无法立即完成,线程不会被挂起,而是可以继续执行其他任务。

特点:

  • 灵活性:线程可以处理更多的连接,因为它们不会因等待I/O操作而被阻塞。
  • 复杂性增加:需要程序员显式地检查操作是否完成,增加了编程难度。
  • 性能提升:在高并发场景下,可以显著减少线程切换带来的开销。

3. 多路复用 (Multiplexing)

​ 多路复用是通过一个线程同时监控多个文件描述符,当某个描述符就绪(通常意味着数据可读,或者写缓冲区可写)时,才对其进行操作。Java中使用Selector(选择器)来实现多路复用。

特点:

  • 高并发能力:一个线程可以处理成千上万个连接,大大提高了服务器的吞吐量。
  • 高效:只有当有I/O操作准备就绪时,才会唤醒线程,避免了不必要的线程切换。
  • 资源节省:相比于阻塞I/O,多路复用模型下的服务器可以更高效地利用系统资源。

注意:

​ 在实际应用中,非阻塞I/O往往与多路复用结合使用。例如,一个服务器可以使用一个Selector来监控多个SocketChannel,当某个SocketChannel有数据可读或可写时,Selector会通知服务器,服务器再使用非阻塞的方式处理这个特定的SocketChannel。

4.NIO VS BIO

4.1 stream vs channel

在Java中,Stream和Channel是两种处理数据流的不同方式,它们分别属于Java的标准IO库和NIO库。下面是这两种概念的详细对比:

Stream(流)

​ Stream是Java标准IO(即blocking IO)模型的一部分,它提供了一种顺序读写数据的方法。Stream分为两种类型:InputStream和OutputStream,分别用于读取和写入数据。这些流可以是字节流(如InputStream, OutputStream)或者是字符流(如Reader, Writer)。

特点:

  • 阻塞性:默认情况下,Stream的操作是阻塞的,即如果读操作没有数据可读,或者写操作无法立即完成,那么调用线程将被阻塞直到操作完成。
  • 单向性:每个Stream都有一个方向,要么只读,要么只写。
  • 自动关闭:使用完Stream后,通常需要调用其close()方法来释放资源。从Java 7开始,try-with-resources语句可以自动关闭实现AutoCloseable接口的资源,包括Stream。

Channel(通道)

​ Channel是Java NIO(New IO)模型的一部分,它提供了比Stream更高级别的抽象,允许更高效地处理数据。Channel可以是双向的,意味着它们可以用于读取和写入数据。主要的Channel类型包括FileChannelSocketChannelServerSocketChannelDatagramChannel

特点:

  • 非阻塞性:Channel可以配置为阻塞或非阻塞模式。在非阻塞模式下,如果读操作没有数据可读,或者写操作无法立即完成,操作将立即返回,而不是阻塞线程。
  • 缓冲区操作:Channel操作总是通过缓冲区(Buffer)进行,数据从通道读入缓冲区,或者从缓冲区写入通道。
  • 多路复用:Channel可以与Selector一起使用,实现多路复用,允许一个线程监控多个Channel的I/O操作,提高并发处理能力。

总结

  • 适用场景:Stream更适合于处理较小的数据集或简单的文件操作,而Channel更适合于处理大量的数据,尤其是网络通信和大型文件操作,因为它提供了更高的性能和更好的并发能力。
  • 编程复杂性:Stream的API相对简单,易于使用;而Channel和NIO的API更复杂,但提供了更强大的功能和更高的效率。
  • 资源管理:无论是Stream还是Channel,都应该适当地管理资源,确保在不再需要时关闭它们,以避免资源泄露。

4.2. IO模型

​ 在Java中,I/O操作的模型可以基于同步/异步和阻塞/非阻塞这两个维度进行分类。

4.2.1 同步阻塞I/O(Synchronous Blocking I/O)

定义:同步阻塞I/O是最传统的I/O模型,当线程调用I/O操作(如读或写)时,该线程将被阻塞,直到操作完成。这意味着在操作完成前,线程不能执行其他任何任务。

特点

  • 简单易用,代码逻辑清晰。
  • 每个I/O操作都需要独占一个线程,不适合高并发场景,可能导致线程资源耗尽。
  • 常见于使用InputStreamOutputStreamSocketServerSocket的场景。

示例:

使用传统的InputStreamOutputStream进行文件读写:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;public class SyncBlockingIOExample {public static void main(String[] args) {try (FileInputStream fis = new FileInputStream("input.txt");FileOutputStream fos = new FileOutputStream("output.txt")) {byte[] buffer = new byte[1024];int bytesRead;while ((bytesRead = fis.read(buffer)) != -1) {fos.write(buffer, 0, bytesRead);}} catch (IOException e) {e.printStackTrace();}}
}

4.2.2 同步非阻塞I/O(Synchronous Non-Blocking I/O)

定义:在同步非阻塞I/O中,线程调用I/O操作后不会被阻塞。如果操作不能立即完成,方法将立即返回,通常返回一个特殊值(如-1或0)或抛出异常,表示操作未完成。

特点

  • 需要轮询操作状态,直到操作完成。
  • 更高的线程利用率,因为线程可以在等待I/O时执行其他任务。
  • 实现较复杂,需要处理轮询和状态检查。
  • 基于Java NIO的ChannelsBuffers,通过调用configureBlocking(false)将通道设为非阻塞模式。

示例:

使用NIO的FileChannel进行非阻塞读写:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.ByteBuffer;public class SyncNonBlockingIOExample {public static void main(String[] args) {try (FileInputStream fis = new FileInputStream("input.txt");FileOutputStream fos = new FileOutputStream("output.txt");FileChannel inChannel = fis.getChannel();FileChannel outChannel = fos.getChannel()) {ByteBuffer buffer = ByteBuffer.allocate(1024);inChannel.configureBlocking(false);while (inChannel.read(buffer) > 0) {buffer.flip();outChannel.write(buffer);buffer.clear();}} catch (IOException e) {e.printStackTrace();}}
}

4.2.3 同步多路复用I/O(Synchronous Multiplexing I/O)

定义:同步多路复用I/O模型使用Selector(选择器)来监控多个Channel的事件。当线程调用Selector.select()时,它将阻塞,直到至少有一个Channel的事件(如可读、可写、连接请求等)发生。

特点

  • 允许一个线程管理多个Channel,提高了并发性。
  • 通过SelectorSelectionKey机制,可以高效地处理大量并发连接。
  • 适用于网络服务器场景,如Web服务器和聊天服务器。
  • 基于Java NIO框架。

示例:

使用NIO的FileChannel进行非阻塞读写:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Set;public class SyncMultiplexingIOExample {public static void main(String[] args) throws IOException {try (Selector selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open()) {serverSocketChannel.socket().bind(new InetSocketAddress(8080));serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);while (true) {if (selector.select() > 0) {Set<SelectionKey> keys = selector.selectedKeys();for (SelectionKey key : keys) {if (key.isAcceptable()) {ServerSocketChannel ssc = (ServerSocketChannel) key.channel();SocketChannel clientChannel = ssc.accept();clientChannel.configureBlocking(false);clientChannel.register(selector, SelectionKey.OP_READ);}}keys.clear();}}}}
}

4.2.4 异步非阻塞I/O(Asynchronous Non-Blocking I/O)

定义:在异步非阻塞I/O模型中,线程发起I/O操作后立即返回,无需等待操作完成。当操作完成时,线程将通过回调函数或事件通知被异步地告知。

特点

  • 最高效的I/O模型,线程完全不被阻塞,可以立即执行其他任务。
  • 通过AsynchronousChannel接口及其子类实现,如AsynchronousFileChannelAsynchronousSocketChannel
  • 适用于高并发和高性能的场景,如大数据处理和高负载网络服务器。
  • Java 7引入了异步非阻塞I/O模型。

示例:

使用NIO的AsynchronousFileChannel进行异步文件读写:

import java.io.IOException;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.ByteBuffer;
import java.util.concurrent.CountDownLatch;public class AsyncNonBlockingIOExample {public static void main(String[] args) throws IOException, InterruptedException {AsynchronousFileChannel inChannel = AsynchronousFileChannel.open(Paths.get("input.txt"), StandardOpenOption.READ);AsynchronousFileChannel outChannel = AsynchronousFileChannel.open(Paths.get("output.txt"), StandardOpenOption.WRITE);ByteBuffer buffer = ByteBuffer.allocate(1024);CountDownLatch latch = new CountDownLatch(1);inChannel.read(buffer, 0, buffer, 0, (channel, result) -> {buffer.flip();outChannel.write(buffer, 0, buffer, 0, null);latch.countDown();});latch.await();inChannel.close();outChannel.close();}
}

注意:异步模型需要底层操作系统(Kernel)提供支持

  • Windows 系统通过 IOCP 实现了真正的异步 IO
  • Linux 系统异步 IO 在 2.6 版本引入,但其底层实现还是用多路复用模拟了异步 IO,性能没有优势

4.2.5 异步阻塞I/O(Asynchronous Blocking I/O)

定义:理论上不存在这种模型,因为“异步”意味着操作在后台执行,线程不会被阻塞。因此,异步阻塞I/O是一个矛盾的概念,实践中不会出现。

4.2.6 总结

​ 选择合适的I/O模型对于性能和资源管理至关重要。高并发场景下,同步非阻塞I/O或同步多路复用I/O模型是常见选择,而在需要极致性能和响应速度的场景下,异步非阻塞I/O模型则是首选。

4.3 零拷贝

零拷贝(Zero-Copy)概念

​ 零拷贝技术是指在数据从一个地方传输到另一个地方的过程中,数据不需要在用户空间和内核空间之间复制,或者至少减少这种复制的次数,以此来提高系统的效率。在传统的I/O操作中,数据从网络或磁盘读取时,首先会被复制到内核空间的缓冲区,然后再从内核空间复制到用户空间的缓冲区。相反,在零拷贝中,数据可以直接在内核空间处理,或者直接从内核空间传递给网络设备,从而减少了CPU的复制操作,降低了系统开销,提高了数据传输的效率。

零拷贝的来源

​ 零拷贝的概念最早出现在操作系统设计中,旨在解决传统I/O操作中数据复制带来的性能瓶颈。在早期的计算机系统中,所有的I/O操作都需要经过用户空间和内核空间的多次数据复制,这在高速网络和大容量磁盘变得普遍之后,逐渐成为了性能的瓶颈。

关键技术点

  • 直接I/O:允许应用程序直接访问磁盘设备,跳过文件系统的缓存机制。
  • 内存映射(MMAP):将文件映射到内存,使得文件数据像内存一样被访问,减少复制。
  • Sendfile:Linux系统调用,可以从一个文件描述符直接传输数据到另一个,避免中间复制。
  • DMA(Direct Memory Access):硬件级别的技术,允许数据直接在设备和内存之间传输,无需CPU参与。

Java中的实现:

​ Java通过NIO(New I/O)框架支持零拷贝技术。NIO引入了FileChannelSocketChannel等类,它们提供了更高效的I/O操作。具体的说,FileChannel.transferTo()FileChannel.transferFrom()方法可以将数据直接从文件通道传输到套接字通道,或反之亦然,而不需要将数据加载到缓冲区,从而实现了零拷贝。

​ 举个例子,假设你需要将一个大文件的内容发送到网络,传统的做法是先将文件内容读入缓冲区,然后将缓冲区的内容写入网络。这涉及到两次复制操作:一次从磁盘到缓冲区,另一次从缓冲区到网络。而在使用transferTo()方法时,数据可以直接从磁盘传输到网络,而不需要中间缓冲区,这就减少了复制次数,实现了零拷贝。

使用ByteBuffer举一个例子:

ByteBuffer和其他Buffer类(如CharBufferShortBuffer等)提供了缓冲区,它们可以被填充或清空而不必直接涉及用户空间和内核空间之间的复制。ByteBuffer可以被直接或间接地用于零拷贝技术中:

  1. 直接缓冲区(Direct Buffer)ByteBuffer.allocateDirect(size)创建的ByteBuffer实例直接映射到物理内存,绕过了Java堆。当这样的缓冲区与FileChannelSocketChannel一起使用时,数据可以直接在物理内存和硬件设备之间传输,而不需要通过Java堆的额外复制。这在某些平台上可以实现真正的零拷贝。
  2. 使用FileChanneltransferTo()transferFrom():这些方法允许数据直接在FileChannelSocketChannel之间传输,而不需要通过ByteBuffer作为中介。这意味着数据可以直接从磁盘传输到网络或反之,而不需要在用户空间和内核空间之间复制。
  3. 使用ByteBufferwrap()方法wrap()方法允许你将现有的字节数组或其他缓冲区包装成一个ByteBuffer,这样就不需要复制数据到一个新的缓冲区。这对于避免不必要的数据复制很有用。
  4. 使用ByteBufferslice()方法slice()方法创建了缓冲区的一个视图,而不会复制底层数据。这意味着可以将一个大的ByteBuffer分割成多个更小的缓冲区,而无需复制数据。

将ByteBuffer与FileChannel结合起来使用:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;public class ZeroCopyExample {public static void main(String[] args) {Path path = Path.of("example.txt");try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ)) {ByteBuffer buffer = ByteBuffer.allocateDirect(1024);long transferred = fileChannel.transferTo(0, fileChannel.size(), System.out);System.out.println("Transferred bytes: " + transferred);} catch (IOException e) {e.printStackTrace();}}
}

注意:

​ 我们要注意,其实刨根问底的说并不存在完全的零拷贝,这里说的零拷贝只是针对于我们应用程序自身而言没有用户级别的拷贝而已。但哪怕是用户级别,也不可能完全没有拷贝操作,只是尽量减少了拷贝,所以我们可以理解术语上的零拷贝其实是指减少数据复制次数的技术,并不是真正的没有拷贝动作。

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

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

相关文章

【算法】二叉树-迭代法实现前后中序遍历

递归的实现就是:每一次递归调用都会把函数的局部变量&#xff0c;参数值和返回地址等压入调用栈中&#xff0c;然后递归返回的时候&#xff0c;从栈顶弹出上一次递归的各项参数&#xff0c;这就是递归为什么可以返回上一层位置的原因 可以用栈实现二叉树的前中后序遍历 1. 前序…

FastAPI 学习之路(四十四)WebSockets

我们之前的分析都是基于http的请求&#xff0c;那么如果是websockets可以支持吗&#xff0c;答案是可以的&#xff0c;我们来看下是如何实现的。 from fastapi import WebSocket, FastAPI from fastapi.responses import HTMLResponseapp FastAPI()html """&…

k8s NetworkPolicy

Namespace 隔离 默认情况下&#xff0c;所有 Pod 之间是全通的。每个 Namespace 可以配置独立的网络策略&#xff0c;来 隔离 Pod 之间的流量。 v1.7 版本通过创建匹配所有 Pod 的 Network Policy 来作为默认的网络策略 默认拒绝所有 Pod 之间 Ingress 通信 apiVersion: …

【趣味数学】求阴影部分面积

题 解法1: 中位线法 既然是中点&#xff0c;就可以用起来&#xff0c;横着不行&#xff0c;竖着来&#xff0c;扩展做辅助线 E是中点S&#xff08;AED) 1/4 S(ABCD) 6 做图中辅助延长线&#xff0c;因为E中点&#xff0c;所以S&#xff08;MEB&#xff09;S(AED) 6 同理E也是…

nfs共享存储配置

目录 一.存储和NFS共享 1.存储的类型分为三种 2.三种存储架构的应用场景 二.NFS共享存储服务 1.NFS简介 2.NFS存储 3.NFS原理 4.软件介绍 三.搭建NFS服务器 1.搭建 2.使用权限&#xff1a; 读写权限 属主&#xff0c;属组权限 客户端创建文件指向同一属主和属组 …

Android使用AndServer在安卓设备上搭建服务端(Java)(Kotlin)两种写法

一直都是通过OkHttp远程服务端进行数据交互&#xff0c;突发奇想能不能也通过OkHttp在局域网的情况下对两个安卓设备或者手机进行数据交互呢&#xff1f; 这样一方安卓设备要当做服务端与另一个安卓设备通过OkHttp进行数据交互即可 当然还可以通过 socket 和 ServerSocket 通…

大数据面试题之Hudi(1)

目录 Hudi的发展历史 描述Hudi的容错和恢复机制 Hudi的核心优势是&#xff1f; Hudi如何处理数据的变更&#xff1f; Hudi如何保证数据的一致性和可靠性&#xff1f; Hudi如何支持数据的多版本并发控制&#xff08;MVCC&#xff09;&#xff1f; Hudi的数据摄取&#xff…

uniapp中使用uni-ui组件库

src目录下新建components目录从uni-ui引入对应的组件目录&#xff0c;如下图 直接使用组件&#xff0c;demo <template><view id"my" data-name"王五" data-age"18">my页面</view><uni-data-select :localdata"local…

为什么要求轨迹平滑?

移动机器人要求轨迹平滑主要是为了确保移动过程的安全、稳定和效率。具体原因如下&#xff1a; 安全性&#xff1a;平滑的轨迹可以减少机器人在移动过程中的震动和冲击&#xff0c;避免对机器人自身结构和周围环境造成损害。稳定性&#xff1a;平滑的轨迹有助于保持机器人的平…

IC后端设计中的shrink系数设置方法

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 在一些成熟的工艺节点通过shrink的方式(光照过程中缩小特征尺寸比例)得到了半节点,比如40nm从45nm shrink得到,28nm从32nm shrink得到,由于半节点的性能更优异,成本又低,漏电等不利因素也可以…

Zookeeper-数据结构

ZooKeeper 的数据模型具有类似于文件系统树结构的特点&#xff0c;但它是专门为分布式应用设计的。 以下是 ZooKeeper 数据结构的主要特点&#xff1a; 层次化的命名空间&#xff1a;ZooKeeper 提供了一个层次化的命名空间&#xff0c;类似于文件系统。每个节点在层次结构中有…

PFH点特征直方图

PFH特征描述子原理 该算法通过参数化查询关键点与其周围邻域点之间的空间差异,形成一个多维度直方图,从而实现对该点的邻域几何属性的描述。 该方法具有以下三个优势: (1)刚性变换不变性,即不受旋转、平移变换的影响; (2)采样一致性,即改变采样密度,特征保…

python连接kafka生产者发送消息

通过pip install kafka-python安装第三方工具 再导入相应的方法就可以连接kafka进行消息发送了。 from kafka import KafkaProducer, KafkaConsumer import jsonproducer KafkaProducer(bootstrap_servers[xxx.xxx.xxx.xxx:9092,xxx.xxx.xxx.xxx:9092],security_protocolSASL…

【数据分享】2021-2100年中国1km分辨率多情景多模式逐月降水量数据集

今天我们给大家分享一份根据IPCC耦合模式比较计划第六阶段&#xff08;CMIP6&#xff09;发布的全球>100 km气候模式数据集以及WorldClim发布的全球高分辨率气候数据集&#xff0c;通过空间降尺度方法得到的2021-2100年中国1km分辨率多情景多模式逐月降水量数据集。 数据来…

04:定时器

定时器 1、定时器怎么定时2、怎样实现计数&#xff1f;2.1、控制寄存器TCON2.2、工作模式寄存器TCOM2.3、定时器T0 3、案例&#xff1a;通过定时器T0控制LED间隔1s亮灭 当定时器用的时候&#xff0c;靠内部震荡电路数数。当配置为定时器使用时&#xff0c;每经过1个机器周期&am…

WPS打开PDF文件的目录

WPS打开PDF文件的目录 其实WPS中PDF文件并没有像Word那样标准的目录&#xff0c;但是倒是有书签&#xff0c;和目录一个效果 点击左上角书签选项&#xff0c;或者使用Alt Shift 1快捷键即可

下载动画人物

1、网址&#xff1a;动画 2、点击Characters 3、搜索人物 4、点击弹出的人物&#xff0c;弹出对话框选择USE THIS CHARACTER 5、下载 6、点击Animations&#xff0c;搜索walk 7、点击UPLOAD CHARACTER&#xff0c;看到男孩步行&#xff0c;选择In Place&#xff0c;点击下载&…

Vue3框架搭建4:配置说明-eslint配置

配置说明&#xff1a; .eslintrc.cjs&#xff1a; /* eslint-env node */ //node环境&#xff0c;并引入一个模块解析补丁 require(rushstack/eslint-patch/modern-module-resolution)module.exports { //继承其他配置root: true, //跟配置文件&#xff0c;ESLint不会在父目…

顺序表(python)

文章目录 1.创建顺序表2.按址查找元素的位置3.增加元素3.1在头部增加元素3.2在尾部增加元素3.3在中间任意位置增加元素 4.删除元素4.1删除第一个元素4.2删除指定的元素 5.顺序表清空 在计算机科学中&#xff0c;数据结构是组织、管理和存储数据的方式。顺序表&#xff0c;也称为…

【安全设备】APT攻击预警平台

一、什么是APT 高级持续性威胁&#xff08;APT&#xff09;是一种高度复杂和长期的网络攻击&#xff0c;旨在通过持续监视和访问特定目标来窃取敏感信息或进行其他恶意活动。这种攻击结合了多种先进的技术手段和社会工程学方法&#xff0c;以极高的隐蔽性实现长期潜伏和信息窃…