rust学习~tokio的io
await
Suspend execution until the result of a Future is ready.
暂停执行,直到一个 Future 的结果就绪。
.awaiting
a future will suspend the current function’s execution until the executor has run the future to completion.
对一个 Future 使用 .await
操作会暂停当前函数的执行,直到执行器(executor)将该 Future 运行至完成
Read the async book for details on how async/await and executors work.
有关异步 / 等待(async/await)和执行器的工作原理的详细信息,请阅读《异步编程指南》(Async Book)。
Editions
await is a keyword from the 2018 edition onwards.
await 是从 2018 版及后续版本开始引入的关键字。
It is available for use in stable Rust from version 1.39 onwards.
从 1.39 版本及以后的稳定版 Rust 中可以使用它。
AsyncReadExt
use tokio::io::{self, AsyncReadExt};
use tokio::fs::File;#[tokio::main]
async fn main() -> io::Result<()> {let mut f = File::open("foo.txt").await?;let mut buffer = Vec::new();// 读取整个文件的内容f.read_to_end(&mut buffer).await?;// String::from_utf8 是 String 类型的一个关联函数// 专门用于把 Vec<u8> 类型的字节向量转换为 String 类型的 UTF - 8 字符串// 它会检查字节向量中的字节序列是否符合 UTF - 8 编码规则// 如果符合则返回一个 Ok(String),若不符合则返回 Err(FromUtf8Error)// 适用于从字节数据(如文件读取、网络接收等)构建字符串,并且需要确保数据是有效的 UTF - 8 编码match String::from_utf8(buffer) {Ok(content) => {println!("文件内容如下:\n{}", content);}Err(e) => {eprintln!("将文件内容转换为字符串时出错: {}", e);}}Ok(())
}
use tokio::io::{self, AsyncReadExt};
use tokio::fs::File;#[tokio::main]
async fn main() -> io::Result<()> {let mut f = File::open("foo.txt").await?;let mut buffer = Vec::new();// 读取整个文件的内容f.read_to_end(&mut buffer).await?;Ok(())
}
为什么说 字节数组 &[u8]
实现了 AsyncRead ?
字节数组切片 &[u8]
实现了 AsyncRead 特征,这意味着它可以作为异步读取操作的数据源,允许以异步的方式从字节数组中读取数据
AsyncRead 特征的作用
AsyncRead 是 tokio 异步运行时库中定义的一个特征,它定义了异步读取操作的接口。其核心方法是 poll_read,该方法用于尝试从数据源中异步读取数据到指定的缓冲区。通过实现 AsyncRead 特征,类型可以参与到异步 I/O 操作中,利用异步运行时的调度机制,在等待数据可读时让出控制权,提高程序的并发性能。
AsyncRead 特征的简化定义如下:
use std::pin::Pin;
use std::task::{Context, Poll};
use tokio::io::Result;pub trait AsyncRead {fn poll_read(self: Pin<&mut Self>,cx: &mut Context<'_>,buf: &mut [u8],) -> Poll<Result<usize>>;
}
self 是实现该特征的类型的可变引用,使用 Pin 确保在异步操作过程中对象的内存位置不会改变
cx 是任务上下文,包含了任务的唤醒器等信息,用于在数据准备好时唤醒任务
buf 用于存储读取数据的缓冲区
Poll 枚举表示操作的结果,可能是 Poll::Ready
表示操作已完成,返回实际读取的字节数;也可能是 Poll::Pending
表示操作还未完成,需要等待。
&[u8] 实现 AsyncRead 的原因
灵活性和通用性:字节数组切片 &[u8]
是一种非常常见且灵活的数据表示方式,它可以表示内存中的一段连续字节数据。实现 AsyncRead 特征后,&[u8]
可以作为异步读取操作的数据源,使得很多使用 AsyncRead 的代码可以直接处理字节数组,无需额外的转换。
例如,在测试代码中,可以使用字节数组模拟文件或网络数据进行异步读取测试。
异步编程的一致性:在异步编程中,希望不同的数据源(如文件、网络套接字、内存缓冲区等)都能以统一的方式进行异步读取操作。通过让 &[u8]
实现 AsyncRead 特征,保持了异步读取操作的一致性,使得代码更加简洁和易于维护。
示例代码
use tokio::io::{self, AsyncReadExt};#[tokio::main]
async fn main() -> io::Result<()> {// 定义一个字节数组,存储了字符串 "Hello, World!" 的 UTF - 8 编码字节数据let data = b"Hello, World!";let mut buffer = [0; 5];// 创建一个字节数组切片 &[u8],作为异步读取的数据源let mut reader = &data[..];// 调用 read 方法(该方法是基于 AsyncRead 特征实现的),异步地从字节数组切片中读取数据到 buffer 中// await 关键字用于等待读取操作完成,最终返回实际读取的字节数let n = reader.read(&mut buffer).await?;println!("Read {} bytes: {:?}", n, &buffer[..n]);Ok(())
}
实际应用场景
测试:在编写异步 I/O 代码的单元测试时,可以使用字节数组模拟不同的数据源,方便进行测试。例如,测试一个异步数据解析器时,可以使用字节数组提供测试数据。
内存数据处理:当需要对内存中的字节数据进行异步处理时,如对加密数据、压缩数据等进行异步解密或解压缩操作,可以直接使用字节数组作为数据源。
字节数组切片 &[u8]
实现 AsyncRead 特征,为异步编程提供了更多的灵活性和一致性,使得字节数组可以方便地作为异步读取操作的数据源。
AsyncWriteExt
use tokio::io::{self, AsyncWriteExt};
use tokio::fs::File;#[tokio::main]
async fn main() -> io::Result<()> {let mut file = File::create("foo.txt").await?;// 将一个 &str 字符串转变成一个字节数组:&[u8;10]// 然后 write 方法又会将这个 &[u8;10] 的数组类型隐式强转为数组切片: &[u8]let n = file.write(b"some bytes").await?;println!("Wrote the first {} bytes of 'some bytes'.", n);Ok(())
}
AsyncWriteExt::write_all
将缓冲区的内容全部写入到写入器中
use tokio::io::{self, AsyncWriteExt};
use tokio::fs::File;#[tokio::main]
async fn main() -> io::Result<()> {let mut file = File::create("foo.txt").await?;file.write_all(b"some bytes").await?;Ok(())
}
tokio::io处理标准的输入/输出/错误
use tokio::fs::File;
use tokio::io;#[tokio::main]
async fn main() -> io::Result<()> {// &[u8] 是字节数组切片let mut reader: &[u8] = b"hello";let mut file = File::create("foo.txt").await?;// 异步的将读取器( reader )中的内容拷贝到写入器( writer )中// 字节数组 &[u8] 实现了 AsyncRead,所以这里可直接使用 readerio::copy(&mut reader, &mut file).await?;Ok(())
}
tokio::io分离读写器
错误写法
io::copy(&mut socket, &mut socket).await
读取器和写入器都是同一个 socket,因此需要对其进行两次可变借用,这明显违背了 Rust 的借用规则
用同一个 socket 是不行的,为了实现目标功能,必须将 socket 分离成一个读取器和写入器
任何一个读写器( reader + writer )都可以使用 io::split
方法进行分离,最终返回一个读取器和写入器,两者可以独自使用,例如可以放入不同的任务中。
回声服务端
use tokio::io;
use tokio::net::TcpListener;#[tokio::main]
async fn main() -> io::Result<()> {let listener = TcpListener::bind("127.0.0.1:6142").await?;loop {let (mut socket, _) = listener.accept().await?;tokio::spawn(async move {// split 操作和 io::copy 调用是在同一个异步任务上下文中执行的// 由于它们处于同一个任务中,所以不存在不同任务之间的数据传递开销和同步问题// 任务的执行是连贯的,避免了因为跨任务操作而引入的额外复杂性和性能损耗let (mut rd, mut wr) = socket.split();if io::copy(&mut rd, &mut wr).await.is_err() {eprintln!("failed to copy");}});}
}
回声客户端
use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpStream;#[tokio::main]
async fn main() -> io::Result<()> {let socket = TcpStream::connect("127.0.0.1:6142").await?;let (mut rd, mut wr) = io::split(socket);// 创建异步任务,在后台写入数据tokio::spawn(async move {wr.write_all(b"hello\r\n").await?;wr.write_all(b"world\r\n").await?;// 有时,我们需要给予 Rust 一些类型暗示,它才能正确的推导出类型Ok::<_, io::Error>(())});let mut buf = vec![0; 128];loop {let n = rd.read(&mut buf).await?;if n == 0 {break;}println!("GOT {:?}", &buf[..n]);}Ok(())
}
tokio::spawn
是 Tokio 运行时提供的一个函数,用于创建一个新的异步任务并将其放入任务队列中等待执行。这个新任务会在 Tokio 运行时的调度下异步执行,与当前代码所在的任务是并发关系,而不是顺序执行关系。
当执行到 tokio::spawn
时,它会立即将传入的异步闭包包装成一个新的异步任务并放入 Tokio 运行时的任务队列中,然后代码会继续往下执行,不会等待这个新任务开始执行。
因此,let mut buf = vec![0; 128];
这行代码会紧接着 tokio::spawn
之后执行,而 tokio::spawn
内部的异步任务会在 Tokio 运行时调度到它时才开始执行。
Tokio 运行时的调度是基于事件驱动和任务优先级的,它会根据系统资源和任务的状态动态地决定哪个任务先执行。所以,tokio::spawn
内部的任务可能在 let mut buf = vec![0; 128];
之前执行,也可能在之后执行,甚至可能与后续代码并发执行
假设 tokio::spawn
内部的任务执行需要一些时间(例如网络延迟),而创建 buf 向量的操作很快,那么很可能 let mut buf = vec![0; 128];
会先执行,然后才轮到 tokio::spawn
内部的任务开始执行
C-S修正
cargo run --bin server.rs
cargo run --bin client.rs
上述代码跑起来之后,服务端不退出的话,客户端会一直卡住,客户端加如下函数即可解决
wr.shutdown().await ? ;
手动实现io
use tokio::io::{self, AsyncReadExt, AsyncWriteExt};
use tokio::net::TcpListener;#[tokio::main]
async fn main() -> io::Result<()> {let listener = TcpListener::bind("127.0.0.1:6142").await?;loop {let (mut socket, _) = listener.accept().await?;tokio::spawn(async move {// 此处的缓冲区是一个 Vec 动态数组,它的数据是存储在堆上,而不是栈上// 若改成 let mut buf = [0; 1024];,则存储在栈上// 一个数据如果想在 .await 调用过程中存在,那它必须存储在当前任务内// buf 会在 .await 调用过程中被使用,因此它必须要存储在任务内let mut buf = vec![0; 1024];loop {match socket.read(&mut buf).await {// 返回值 `Ok(0)` 说明对端已经关闭Ok(0) => return,Ok(n) => {// Copy the data back to socket// 将数据拷贝回 socket 中if socket.write_all(&buf[..n]).await.is_err() {// 非预期错误,由于我们这里无需再做什么,因此直接停止处理return;}}Err(_) => {// 非预期错误,由于我们无需再做什么,因此直接停止处理return;}}}});}
}
若该缓冲区数组创建在栈上,那每条连接所对应的任务的内部数据结构看上去可能如下所示
struct Task {task: enum {AwaitingRead {socket: TcpStream,buf: [BufferType],},AwaitingWriteAll {socket: TcpStream,buf: [BufferType],}}
}
栈数组要被使用,就必须存储在相应的结构体内,其中两个结构体分别持有了不同的栈数组 [BufferType]
这种方式会导致任务结构变得很大
一般选择缓冲区长度往往会使用分页长度(page size),因此使用栈数组会导致任务的内存大小变得很奇怪甚至糟糕:
$page-size + 一些额外的字节
编译器会进一步优化 async 语句块的布局,而不是像上面一样简单的使用 enum
在实践中,变量也不会在枚举成员间移动。但是再怎么优化,任务的结构体至少也会跟其中的栈数组一样大
因此通常情况下,使用堆上的缓冲区会高效实用的多
当任务因为调度在线程间移动时,存储在栈上的数据需要进行保存和恢复,过大的栈上变量会带来不小的数据拷贝开销
因此,存储大量数据的变量最好放到堆上
处理 EOF
当 TCP 连接的读取端关闭后,再调用 read 方法会返回 Ok(0)
。此时,再继续下去已经没有意义,因此需要退出循环。
忘记在 EOF 时退出读取循环,是网络编程中一个常见的 bug :
loop {match socket.read(&mut buf).await {Ok(0) => return,// ... 其余错误处理}
}
一旦读取端关闭后,那后面的 read 调用就会立即返回 Ok(0)
,而不会阻塞等待,因此这种无阻塞循环会最终导致 CPU 立刻跑到 100%
,并将一直持续下去,直到程序关闭。
小节
实际上,io::split
可以用于任何同时实现了 AsyncRead 和 AsyncWrite 的值,它的内部使用了 Arc 和 Mutex 来实现相应的功能。如果大家觉得这种实现有些重,可以使用 Tokio 提供的 TcpStream,它提供了两种方式进行分离:
TcpStream::split
会获取字节流的引用,然后将其分离成一个读取器和写入器。但由于使用了引用的方式,它们俩必须和 split 在同一个任务中。 优点就是,这种实现没有性能开销,因为无需 Arc 和 Mutex。
TcpStream::into_split
还提供了一种分离实现,分离出来的结果可以在任务间移动,内部是通过 Arc 实现
相关文章:
rust学习~tokio的io
await Suspend execution until the result of a Future is ready. 暂停执行,直到一个 Future 的结果就绪。 .awaiting a future will suspend the current function’s execution until the executor has run the future to completion. 对一个 Future 使用 .awa…...
JVM--虚拟机
JVM,即虚拟机,可以简单理解为将字节码文件翻译成机器码的机器。 .class文件-->机器码文件 JVM整体组成部分 1.类加载器 负责从磁盘中加载字节码文件到JVM中 2.运行时数据区 按照不同的数据分区进行存储(方法区,堆,栈,本地方…...
【Unity】把Texture的黑色背景改成透明背景
1. 在Project窗口中选择目标Texture 2. 在Inspector窗口中进行如下设置: Texture Type: Sprite (2D and UI)Alpha Source: Input Texture Alpha (如果原图有Alpha通道) 或 From Gray Scale (如果要用灰度值作为透明度)Alpha Is Transparency: ✓ (勾选) 3. 其他建…...
计算机毕业设计SpringBoot+Vue.js华强北商城二手手机管理系统 (源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
利用 Python 爬虫进行跨境电商数据采集
1 引言2 代理IP的优势3 获取代理IP账号4 爬取实战案例---(某电商网站爬取)4.1 网站分析4.2 编写代码4.3 优化代码 5 总结 1 引言 在数字化时代,数据作为核心资源蕴含重要价值,网络爬虫成为企业洞察市场趋势、学术研究探索未知领域…...
Android中使用Robolectric测试点击事件(不需要手机)
文章目录 一、前言二、简单示例三、参考文档 一、前言 Robolectric 是一个由 Google 维护的开源 Android 测试框架,它允许你以 Android 运行时环境运行单元测试。 Robolectric 提供了一个模拟 Android 运行时环境,允许你测试你的代码是否正确地使用 And…...
如何把网络ip改为动态:全面指南
在数字化时代,网络IP地址作为设备在网络中的唯一标识,扮演着至关重要的角色。随着网络环境的不断变化,静态IP地址的局限性逐渐显现,而动态IP地址则因其灵活性和安全性受到越来越多用户的青睐。那么,如何把网络IP改为动…...
文件描述符与重定向
1. open系统调用 在 Linux 中, open() 系统调用用于打开一个文件或设备,并返回一个文件描述符,通过该描述符可以进行文件读写操作。open() 可以用于创建新文件或打开已存在的文件,具体行为取决于传递给它的参数。 需要包含的头文件…...
自然语言处理NLP入门 -- 第六节命名实体识别
1 什么是命名实体识别? 在日常生活中,我们经常会遇到这样的情景:希望从一大段文本中,快速找出所有的人名、地名、组织机构名称、日期、时间等关键信息。举个例子,如果你在阅读一篇关于历史事件的新闻报道时࿰…...
Windows PicPick Professional-v7.3.2-中文版
Windows PicPick Professional-中文版 链接:https://pan.xunlei.com/s/VOKGwGVGWUDl7L8cW4D1A1W4A1?pwdw5qz# - 更新了中文翻译,默认取消检测升级,删除多国语言...
Hue UI展示中文
个人博客地址:Hue UI展示中文 | 一张假钞的真实世界 如果使用开发分支代码如master分支)编译安装,需要自己编译语言文件。例如Hue安装目录为“/opt/hue”,则安装后执行以下命令: $ cd /opt/hue $ make locales 如果…...
【Unity】AI Navigation自动寻路(导航)功能
1.简介以及安装AI Navigation 1.1 简介 AI导航包包含高级组件,允许你在游戏中使用导航网格来整合导航和寻径。有了这个包,你可以在运行时和编辑时构建和使用导航网格,创建动态障碍,并使用链接来允许特定的动作(如跳跃…...
网络安全员证书
软考网络安全员证书:信息安全领域的黄金标准 随着信息技术的飞速发展,网络安全问题日益凸显,网络安全员的需求也日益增加。软考网络安全员证书作为信息安全领域的黄金标准,对于网络安全从业者来说具有重要意义。本文将详细介绍…...
2.你有什么绝活儿?—Java能做什么?
1、Java的绝活儿:要问Java有什么绝活,我觉得它应该算是一位魔法师,会的绝活儿有很多,要说最能拿得出手的当属以下三个。 1.1 平台无关性:Java可以在任何地方施展魔法,无论是Windows、Linux还是Mac…...
使用 ASP.NET Core 创建和下载 zip 文件
对于最近的一个功能,我必须从用 ASP.NET Core 编写的内部网站下载一批文件。在下载文件之前对其进行压缩,结果证明这是一种轻松实现多文件下载的好方法。.NET 提供了所有需要的功能,在本文中,我将向您展示如何实现它。 首先&#…...
数据结构之队列
一、队列的概念 队列是一个有序列表,可以用数组或者是链表来实现的。遵循的是先入先出的原则,就是先存入队列的数据要先取出,后面存的需要后面取出。插入的一端称为队尾,删除的一端称为队头,队列里没有元素就称它为空…...
微信小程序读取写入NFC文本,以及NFC直接启动小程序指定页面
一、微信小程序读取NFC文本(yyy优译小程序实现),网上有很多通过wx.getNFCAdapter方法来监听读取NFC卡信息,但怎么处理读取的message文本比较难找,现用下面方法来实现,同时还解决几个问题,1、在回调方法中this.setData不更新信息,因为this的指向问题,2、在退出页面时,…...
【Godot4.3】自定义简易菜单栏节点ETDMenuBar
概述 Godot中的菜单创建是一个复杂的灾难性工作,往往无从下手,我也是不止一次尝试简化菜单的创建。 从自己去年的发明“简易树形数据”用于简化Tree控件获得灵感,于是尝试编写了用于表示菜单数据的EasyMenuData类,以及对应的纯文…...
win7电脑上最好安装 Python什么版本?
李升伟 整理 在 Windows 7 上安装 Python 时,需考虑系统兼容性和安全性。以下是具体建议: --- ### **推荐版本:Python 3.8.x** 1. **兼容性** Python 3.8 是最后一个官方支持 Windows 7 的版本(需安装系统更新至 **SP1** …...
苍穹外卖-阿里云OSS文件上传
苍穹外卖-阿里云OSS文件上传 一、阿里云OSS简介**获取AccessKey**获取enpoint 二、代码实现1 引入依赖2 定义OSS相关配置2.1 application-dev.yml2.2 application.yml 3 读取OSS配置3.1 AliOssProperties 4 生成OSS工具类对象4.1 AliOssUtil4.2 OssConfiguration2.5 CommonCont…...
一周热点:基于向量的推理,而非文本
背景介绍 大型语言模型(LLMs):大型语言模型(如GPT-2)可以通过生成思维链(CoT)来提高性能。CoT是将回应提示的过程分解为一系列步骤的中间文本标记。然而,大部分CoT文本旨在保持流畅性(例如“a”、“of”、“we know that”),而非推理(例如“a + b = c”)。这导致了…...
Tagr 5 for Mac v5.8.0 [MAS] 音频标签编辑工具 支持M、Intel芯片
Tagr 5应用介绍 Tagr 5 是一款功能强大的音乐标签编辑工具,专为macOS用户设计。它旨在帮助用户高效地管理和编辑音乐文件的标签(Metadata),尤其适合那些有大量音乐文件的用户。通过Tagr 5,用户可以轻松地编辑和更新音…...
【linux】详谈 环境变量
目录 一、基本概念 二、常见的环境变量 取消环境变量 三、获取环境变量 通过代码获取环境变量 环境变量的特性 1. getenv函数:获取指定的环境变量 2. environ获取环境变量 四、本地变量 五、定义环境变量的方法 临时定义(仅对当前会话有效) 永…...
【PyQt5】python可视化开发:PyQt5介绍,开发环境搭建快速入门
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...
数据结构1-4 队列
一、队列是什么? 先举一个日常例子,排队买饭。 排队买饭 大家按先来后到的顺序,在窗口前排队买饭,先到先得,买完之后走开,轮到下一位买,新来的人排在队尾,不能插队。 可见&#x…...
地弹与振铃
地弹(Ground Bounce)和振铃(Ringing)是数字电路中常见的信号完整性问题,两者都与高速开关和寄生参数有关,但表现形式和成因不同。以下是它们的对比及解决方法: 1. 地弹(Ground Bounc…...
单一职责原则(设计模式)
目录 问题: 定义: 解决: 方式 1:使用策略模式 示例:用户管理 方式 2:使用装饰者模式 示例:用户操作 方式 3:使用责任链模式 示例:用户操作链 总结 推荐 问题&a…...
蓝桥杯深秋的苹果
题目 当深秋的苹果树丰收时,村庄的居民们兴致勃勃地采摘着红彤彤的苹果。他们将采摘下来的 NN 个苹果排成了一排,形成了一个苹果序列 AA,第 ii 个苹果的甜度值为 AiAi(1≤i≤N1≤i≤N)。 现在村民需要将苹果序列划…...
【网页视频背景闪烁问题分析与解决方案】
网页视频背景闪烁问题分析与解决方案 现象描述 在开发带有视频背景的网页时,我们遇到了一个棘手的问题:当用户滚动页面时,视频背景区域会出现明显的闪烁现象,具体表现为: 文字内容会突然变亮或变大视频背景会突然变…...
Server 6 ,VMware 解析,ESXi 与 Workstation 应用指南(VMware ESXi 与 VMware Workstation)
目录 前言 一、VMware公司介绍 二、主要产品和技术 2.1 服务器虚拟化 2.2 桌面虚拟化 2.3 网络虚拟化与安全 2.4 云管理平台 2.5 存储与可用性 三、VMware ESXi 3.1 ESXi 是什么“超级神器” 3.2 安装与网络配置如何掌握 3.3 访问与管理如何玩转 3.4 下载地址与官网…...
今天你学C++了吗?——string(上)
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...
使用通义万相Wan2.1进行视频生成
使用通义万相Wan2.1进行视频生成 源代码准备运行环境准备创建Python虚拟环境并激活安装依赖包 模型下载生成视频官网的视频生成例子简单描述场景视频生成示例详细描述场景视频生成示例 最近通义万相开源了其视频生成模型。模型有两个版本,一个是1.3B的,一…...
Windows在多网络下指定上网接口
Windows在多网络下指定上网接口 一、说明 设备情况:win11,同时连接了有线网和WLAN,有线网连接着NAS必须保持连接。需求:有些情况时,有线网无网络而WLAN有网,但系统仍走着有线导致无法上网。 二、方法 过…...
前端正则表达式完全指南:从入门到实战
文章目录 第一章:正则表达式基础概念1.1 什么是正则表达式1.2 正则表达式工作原理1.3 基础示例演示 第二章:正则表达式核心语法2.1 元字符大全表2.2 量词系统详解2.3 字符集合与排除 第三章:前端常用正则模式3.1 表单验证类3.1.1 邮箱验证3.1…...
【愚公系列】《Python网络爬虫从入门到精通》038-SQLite数据库
标题详情作者简介愚公搬代码头衔华为云特约编辑,华为云云享专家,华为开发者专家,华为产品云测专家,CSDN博客专家,CSDN商业化专家,阿里云专家博主,阿里云签约作者,腾讯云优秀博主,腾讯云内容共创官,掘金优秀博主,亚马逊技领云博主,51CTO博客专家等。近期荣誉2022年度…...
npx degit 问题:could not fetch remote...
问题与处理策略 问题描述 npx degit dream-num/univer-sheet-start-kit univer-sheet-start-kit执行上述指令,报如下错误 ! could not fetch remote https://github.com/dream-num/univer-sheet-start-kit ! could not find commit hash for HEAD# 翻译无法获取远…...
空投与转账:Solana代币核心概念及代码实战精解
目录 1.空投和转账概念 1.1.空投(Airdrop) 1.2.转账(Transfer) 2.Solana 代币创建与空投核心代码总结 2.1. 代币创建核心代码 2.2. 添加元数据核心代码 2.3. 空投代币核心代码 3.效果图展示 1.空投和转账概念 1.1.空投(Airdrop) 创建新代币: 空投是铸造(Mint)新代币…...
Rust~tokio的AsyncRead
AsyncRead trait 定义 介绍 /// This trait is analogous to the [std::io::Read] trait, but integrates with /// the asynchronous task system. In particular, the [poll_read] method, /// unlike [Read::read], will automatically queue the current task for wakeup…...
NO.22十六届蓝桥杯备战|一维数组|七道练习|冒泡排序(C++)
B2093 查找特定的值 - 洛谷 题⽬要求下标是从0开始的,和数组的下标是吻合的,存放数据应该从下标0开始n的取值范围是1~10000数组中存放的值的绝对值不超10000,说明int类型就⾜够了找到了输出下标,找不到要输出-1,这⼀点…...
Linux下的网络通信编程
在不同主机之间,进行进程间的通信。 1解决主机之间硬件的互通 2.解决主机之间软件的互通. 3.IP地址:来区分不同的主机(软件地址) 4.MAC地址:硬件地址 5.端口号:区分同一主机上的不同应用进程 网络协议…...
【JavaWeb13】了解ES6的核心特性,对于提高JavaScript编程效率有哪些潜在影响?
文章目录 🌍一. ES6 新特性❄️1. ES6 基本介绍❄️2. 基本使用2.1 let 声明变量2.2 const 声明常量/只读变量2.3 解构赋值2.4 模板字符串2.5 对象拓展运算符2.6 箭头函数 🌍二. Promise❄️1. 基本使用❄️2. 如何解决回调地狱问题2.1回调地狱问题2.2 使…...
每日一题之屏蔽信号
问题描述 在与三体文明的对抗中,人类联邦探测到了两个重要的信号源,分别用非负整数 aa 和 bb 来表示。 为了抵御三体舰队的入侵,科学家们制定出一项关键策略——屏蔽信号,目标是要让 aa、bb 这两个信号源其中之一的数值归零。 在…...
TCP如何保证可靠性
目录 回顾TCP协议TCP报文头部 TCP如何保证可靠性?校验和序列号确认应答机制(ACK)超时重传机制连接管理机制(三次握手和四次挥手)流量控制滑动窗口滑动机制 拥塞控制慢开始 & 拥塞避免快重传 & 快恢复 回顾TCP协…...
HTTP协议深度解析:从Tomcat到HTTPS的全方位探索
目录 引言 一、Tomcat部署与Servlet容器 1.1 Tomcat部署流程 1.2 Tomcat与Servlet 二、HTTP协议的基础构成 2.1 URL 2.2 HTTP请求与响应 2.3 HTTP状态码 三、计算机网络与数据传输 3.1 局域网与路由器 3.2 IP地址与MAC地址 3.3 域名与DNS 四、HTTPS协议与数据加密…...
互联网医院实时数据监测智能分析系统设计概述(下)
阶段4:可视化仪表盘与用户界面开发 在这一阶段,我们将使用 Plotly Dash 来设计一个实时预测仪表盘,用于展示疾病传播趋势、医生评估信息等。我们还将实现实时数据更新与展示,确保数据能够及时反映系统中的变化。 1. 设计实时预测仪表盘 步骤 1:安装 Dash 依赖 首先,确…...
性能测试测试策略制定|知名软件测评机构经验分享
随着互联网产品的普及,产品面对的用户量级也越来越大,能抗住指数级增长的瞬间访问量以及交易量是保障购物体验是否顺畅的至关重要的一环,而我们的性能测试恰恰也是为此而存在的。 性能测试是什么呢?性能测试要怎么测呢?…...
【AI+智造】在阿里云Ubuntu 24.04上部署DeepSeek R1 14B的完整方案
作者:Odoo技术开发/资深信息化负责人 日期:2025年2月28日 一、部署背景与目标 DeepSeek R1作为国产大语言模型的代表,凭借其强化学习驱动的推理能力,在复杂任务(如数学问题、编程逻辑)中表现优异。本地化部…...
蓝桥真题讲解
温馨提示:本系列文章非所有题都对对b组适用,b组的小伙伴请挑题看! 目录 第一题 题目链接 题目解析 代码原理 代码编写 本题总结 第二题 题目链接 题目解析 代码原理 代码编写 本题总结 第三题 题目链接 题目解析 代码原理 …...
javaweb将上传的图片保存在项目文件webapp下的upload文件夹下
前端HTML表单 (upload.html) 首先,创建一个HTML页面,允许用户选择并上传图片。 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>图片上传</title> </head> <…...
北京大学DeepSeek与AIGC应用(PDF无套路下载)
近年来,人工智能技术飞速发展,尤其是大模型和生成式AI(AIGC)的突破,正在重塑各行各业的生产方式与创新路径。 北京大学联合DeepSeek团队推出的内部研讨教程《DeepSeek与AIGC应用》,以通俗易懂的方式系统解…...