【Rust自学】20.1. 最后的项目:单线程Web服务器
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
20.1.1. 什么是TCP和HTTP
Web 服务器涉及的两个主要协议是超文本传输协议(Hypertext Transfer Protocol,简称HTTP)和传输控制协议(Transmission Control Protocol,简称TCP)。这两种协议都是请求-响应协议,即客户端发起请求,然后服务器监听请求并向客户端提供响应。这些请求和响应的内容由协议定义。
TCP是较低级别的协议,它描述信息如何从一台服务器传输到另一台服务器的详细信息,但不指定该信息是什么。HTTP通过定义请求和响应的内容构建在TCP之上。从技术上讲,可以将HTTP与其他协议结合使用,但在绝大多数情况下,HTTP通过TCP发送数据。我们将使用TCP和HTTP请求和响应的原始字节。
20.1.2. 监听TCP
了解了以上信息之后,我们就开始实践吧!首先创建这个项目:
cargo new web_server
打开main.rs
,初步的代码如下:
use std::net::TcpListener;fn main() {let listener = TcpListener::bind("127.0.0.1:7878").unwrap();for stream in listener.incoming() {let stream = stream.unwrap();println!("Connection established!");}
}
-
std::net::TcpListener
是一个标准库提供的监听TCP的模块 -
TcpListener::bind
函数会监听传进去的这个地址,我们这里传进去的是"127.0.0.1:7878",也就是本地的7878接口,它的返回类型是一个Result<T, E>
,需要使用unwrap
进行错误处理。如果能成功监听,就会返回TcpListener
类型赋给变量listener
。 -
TcpListener
类型上有incoming
方法,它会返回一个产生流序列的这个迭代器,也就是TcpStream
流,而单个流就表示客户端和服务器之间打开了一个连接,而使用for
循环就会依次处理每一个连接,生成一系列的流让我们处理。
让我们尝试运行这段代码。在终端调用cargo run
然后加载 Web 浏览器中的127.0.0.1:7878
。浏览器应该显示一条错误消息,例如“连接重置”,因为服务器当前没有发回任何数据。但是当你查看终端时,你应该会看到浏览器连接到服务器时打印的几条消息。
20.1.3. 读取请求
我们已经实现了监听TCP,接下来我们来尝试读取请求。我们直接在上文的代码上修改:
use std::{ io::{prelude::*, BufReader}, net::{TcpListener, TcpStream},
}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); for stream in listener.incoming() { let stream = stream.unwrap(); handle_connection(stream); }
} fn handle_connection(mut stream: TcpStream) { let buf_reader = BufReader::new(&stream); let http_request: Vec<_> = buf_reader .lines() .map(|result| result.unwrap()) .take_while(|line| !line.is_empty()) .collect(); println!("Request: {:#?}", http_request);
}
-
我们定义了一个名为
handle_connection
的函数,用于处理客户端连接。参数stream
是一个可变的TcpStream
类型实例,用于与客户端通信。TcpStream
的内部状态可能会随着数据读取和写入发生变化,因此需要将其声明为mut
。 -
我们通过
BufReader
包裹了stream
,创建了一个缓冲读取器buf_reader
。 -
我们使用
map(|result| result.unwrap())
解包Result
,提取其中的字符串。如果读取发生错误,程序会因unwrap
调用而恐慌。 -
take_while(|line| !line.is_empty())
过滤迭代器中的元素,直到遇到空行为止。HTTP请求以空行(""
)标志请求头结束,因此我们仅收集非空行。 -
我们将所有非空行收集到一个向量
Vec<_>
中,存储为http_request
。 -
使用
println!
打印出来http_request
。
试一下:
终端输出的信息如下:
Request: ["GET / HTTP/1.1","Host: 127.0.0.1:7878","Connection: keep-alive","sec-ch-ua: \"Not(A:Brand\";v=\"99\", \"Google Chrome\";v=\"133\", \"Chromium\";v=\"133\"","sec-ch-ua-mobile: ?0","sec-ch-ua-platform: \"macOS\"","Upgrade-Insecure-Requests: 1","User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36","Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Sec-Fetch-Site: none","Sec-Fetch-Mode: navigate","Sec-Fetch-User: ?1","Sec-Fetch-Dest: document","Accept-Encoding: gzip, deflate, br, zstd","Accept-Language: zh-US,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6",
]
HTTP是基于文本的协议,它的请求采用以下格式:
Method Request-URI HTTP-Version CRLF
headers CRLF
message-body
第一行是请求行,保存有关客户端请求的信息。请求行的第一部分指示正在使用的方法,例如GET
或POST
,它描述了客户端如何发出此请求。我们的客户使用了GET
请求,这意味着它正在询问信息。
请求行的下一部分是/
,它表示客户端请求的统一资源标识符 (URI):URI几乎与统一资源定位符(URL)相同,但不完全相同。URI和URL之间的区别对于本章的目的并不重要,但HTTP 规范使用了术语URI,因此我们可以在这里用URL代替URI。
最后一部分是客户端使用的 HTTP 版本,然后请求行以CRLF序列结束。(CRLF代表回车和换行) CRLF序列也可以写成 \r\n
,其中 \r
是回车,\n
是换行。CRLF 序列将请求行与其余请求数据分开。请注意,当打印CRLF时,我们会看到一个新的行而不是 \r\n
。
20.1.4. 编写响应
实现了读取请求,接下来我们来写响应。响应和请求是差不多的格式:
HTTP-Version Status-Code Reason-Phrase CRLF
headers CRLF
message-body
第一行是一个状态行,其中包含响应中使用的HTTP版本、一个数字状态代码,以及状态代码对应的文本描述,最后是一个CRLF序列。
有了格式就好写代码:
let response = "HTTP/1.1 200 OK\r\n\r\n"; stream.write_all(response.as_bytes()).unwrap();
-
HTTP/1.1
是HTTP版本,200是数字状态码,OK
是文本描述,\r\n\r\n
是CRLF序列。 -
我们在
response
中调用as_bytes
将字符串数据转换为字节。stream
上的write_all
方法采用&[u8]
并直接通过连接发送这些字节。由于write_all
操作可能会失败,因此我们使用unwrap
。在实际应用程序中,也可以添加其它错误处理方法。
接下来我们来返回一个真正的HTML文档。在项目根目录建立hello.html
:
然后这么写:
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Hello!</title></head><body><h1>Hello!</h1><p>Hi from Rust</p></body>
</html>
这是一个最小的HTML5文档,带有标题和一些文本。
为了返回HTML,我们需要修改main.rs
。首先引入std::fs
:
use std::fs;
fs
是文件系统包。
然后在handle_connection
函数里稍微修改一下response
变量:
let status_line = "HTTP/1.1 200 OK";
let contents = fs::read_to_string("hello.html").unwrap();
let length = contents.len(); let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); stream.write_all(response.as_bytes()).unwrap();
- 通过
fs
下的read_to_string
方法把文件的内容转化为字符串 - 然后通过
format!
函数把字符串按照刚才写的响应格式放在消息里
完整代码:
use std::{ io::{prelude::*, BufReader}, net::{TcpListener, TcpStream},fs,
}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); for stream in listener.incoming() { let stream = stream.unwrap(); handle_connection(stream); }
} fn handle_connection(mut stream: TcpStream) {let buf_reader = BufReader::new(&stream);let http_request: Vec<_> = buf_reader.lines().map(|result| result.unwrap()).take_while(|line| !line.is_empty()).collect();let status_line = "HTTP/1.1 200 OK";let contents = fs::read_to_string("hello.html").unwrap();let length = contents.len();let response =format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}");stream.write_all(response.as_bytes()).unwrap();
}
试一下:
20.1.5. 有选择地响应
现在,无论客户端请求什么,我们的Web服务器都会返回文件中的HTML。让我们添加功能来检查浏览器是否在正常访问。正常访问就是访问127.0.0.1:7878/
或127.0.0.1:7878
。在返回HTML文件之前,如果浏览器请求其他任何内容,则返回错误。
在项目根目录下创建一个404.html
,里面的内容如下:
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Hello!</title></head><body><h1>Oops!</h1><p>Sorry, I don't know what you're asking for.</p></body>
</html>
我们把之前返回HTML的代码部分放在if
判断里,如果是正常的访问就返回正常的内容,否则就返回404.html
:
fn handle_connection(mut stream: TcpStream) { let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); if request_line == "Get / HTTP/1.1\r\n" { let status_line = "HTTP/1.1 200 OK"; let contents = fs::read_to_string("hello.html").unwrap(); let length = contents.len(); let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); stream.write_all(response.as_bytes()).unwrap(); } else { let status_line = "HTTP/1.1 404 NOT FOUND"; let contents = fs::read_to_string("404.html").unwrap(); let length = contents.len(); let response = format!( "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}" ); stream.write_all(response.as_bytes()).unwrap(); }
}
- 我们删去了打印出请求的部分,反正用不到。
- 通过请求行来判断用户是否是正常访问。正常访问的流程不变,非正常访问就返回
404.html
的内容。
目前的代码有很多重复的地方,我们来重构一下:
fn handle_connection(mut stream: TcpStream) { let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = if request_line == "GET / HTTP/1.1" { ("HTTP/1.1 200 OK", "hello.html") } else { ("HTTP/1.1 404 NOT FOUND", "404.html") }; let contents = fs::read_to_string(filename).unwrap(); let length = contents.len(); let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); stream.write_all(response.as_bytes()).unwrap();
}
通过元组的模式匹配和if
语句来确定status_line
和filename
的值。
试一下:
正常访问:
非正常访问:
20.1.5. 总结
以下是源代码:
main.rs
:
use std::{ io::{prelude::*, BufReader}, net::{TcpListener, TcpStream}, fs,
}; fn main() { let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); for stream in listener.incoming() { let stream = stream.unwrap(); handle_connection(stream); }
} fn handle_connection(mut stream: TcpStream) { let buf_reader = BufReader::new(&stream); let request_line = buf_reader.lines().next().unwrap().unwrap(); let (status_line, filename) = if request_line == "GET / HTTP/1.1" { ("HTTP/1.1 200 OK", "hello.html") } else { ("HTTP/1.1 404 NOT FOUND", "404.html") }; let contents = fs::read_to_string(filename).unwrap(); let length = contents.len(); let response = format!("{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}"); stream.write_all(response.as_bytes()).unwrap();
}
hello.html
:
<!DOCTYPE html>
<html lang="en">
<head> <meta charset="utf-8"> <title>Hello!</title>
</head>
<body>
<h1>Hello!</h1>
<p>Hi from Rust</p>
</body>
</html>
404.html
:
<!DOCTYPE html>
<html lang="en">
<head> <meta charset="utf-8"> <title>Hello!</title>
</head>
<body>
<h1>Oops!</h1>
<p>Sorry, I don't know what you're asking for.</p>
</body>
</html>
相关文章:
【Rust自学】20.1. 最后的项目:单线程Web服务器
喜欢的话别忘了点赞、收藏加关注哦(加关注即可阅读全文),对接下来的教程有兴趣的可以关注专栏。谢谢喵!(・ω・) 20.1.1. 什么是TCP和HTTP Web 服务器涉及的两个主要协议是超文本传输协议(Hypertext T…...
LabVIEW涡轮诊断系统
一、项目背景与行业痛点 涡轮机械是发电厂、航空发动机、石油化工等领域的核心动力设备,其运行状态直接关系到生产安全与经济效益。据统计,涡轮故障导致的非计划停机可造成每小时数十万元的经济损失,且突发故障可能引发严重安全事故。传统人…...
想品客老师的第十天:类
类是一个优化js面向对象的工具 类的声明 //1、class User{}console.log(typeof User)//function//2、let Hdclass{}//其实跟1差不多class Stu{show(){}//注意这里不用加逗号,对象才加逗号get(){console.log(后盾人)}}let hdnew Stu()hd.get()//后盾人 类的原理 类…...
注解(Annotation)
注解(Annotation)在 Java 中可以用来简化类的使用,使得被注解的类能够被自动发现、自动创建并在需要的地方直接调用,而不需要手动创建实例。具体来说,注解是用来标识类、方法、字段等的,它们通常与一些框架…...
使用开源项目:pdf2docx,让PDF转换为Word
目录 1.安装python 2.安装 pdf2docx 3.使用 pdf2docx 转换 PDF 到 Word pdf2docx:GitCode - 全球开发者的开源社区,开源代码托管平台 环境:windows电脑 1.安装python Download Python | Python.org 最好下载3.8以上的版本 安装时记得选择上&#…...
编程AI深度实战:AI编程工具哪个好? Copilot vs Cursor vs Cody vs Supermaven vs Aider
Cursor自己可以看成一个IDE,而且有强大的RAG功能,这让它对你的意图感知非常厉害,可以精确补全,可以感受代码片段 Aider可以看作一个袖珍,灵活,强大的扳手,怎么用都行,可以放在脚本里调用,可以看代码,可以修改代码。相比Cursor而言,它感受的是文件级别,颗粒度有些不…...
如何安全地管理Spring Boot项目中的敏感配置信息
在开发Spring Boot应用时,我们经常需要处理一些敏感的配置信息,比如数据库密码、API密钥等。以下是一个最佳实践方案: 1. 创建配置文件 application.yml(版本控制) spring:datasource:url: ${MYSQL_URL:jdbc:mysql…...
为AI聊天工具添加一个知识系统 之77 详细设计之18 正则表达式 之5
本文要点 昨天讨论了 本项目(AI聊天工具添加一个知识系统)中正则表达式模板的设计中可能要考虑到的一些问题(讨论到的内容比较随意,暂时无法确定 那些考虑 是否 应该是正则表达式模板设计要考虑的以及 是否完整)。今天…...
Ubuntu下Tkinter绑定数字小键盘上的回车键(PySide6类似)
设计了一个tkinter程序,在Win下绑定回车键,直接绑定"<Return>"就可以使用主键盘和小键盘的回车键直接“提交”,到了ubuntu下就不行了。经过搜索,发现ubuntu下主键盘和数字小键盘的回车键,名称不一样。…...
安全实验作业
一 拓扑图 二 要求 1、R4为ISP,其上只能配置IP地址;R4与其他所有直连设备间均使用共有IP 2、R3-R5-R6-R7为MGRE环境,R3为中心站点; 3、整个OSPF环境IP基于172.16.0.0/16划分; 4、所有设备均可访问R4的环回&#x…...
NOTEPAD++编写abap
参考下面三个链接 Notepad ABAP代码高亮显示_notepad代码高亮颜色-CSDN博客 百度安全验证 ABAP Syntax Highlighting in Notepad Part 2 - SAP Community 最后XML文件看看你可以自己增加些新语法的高亮显示...
基于python的体育新闻数据可视化及分析
项目 :北京冬奥会体育新闻数据可视化及分析 摘 要 随着社会的不断进步与发展,新时代下的网络媒体获取的信息也更加庞大和繁杂,相比于传统信息来源更加难以分析和辨别,造成了新时代媒体从业者撰写新闻的难度。在此背景下ÿ…...
C# 精炼题18道题(类,三木运算,Switch,计算器)
1.数组元素和 2.数组元素乘积 3.数组元素平均数 4.数组中最大值 5.数组中的偶数 6.数组中的阶乘 7.数组反转 8.字符串反转 9.回文字符串 10.检查回文 11.最小最大值 12.找素数 13.字符串中的最长无重复字符串 14.字符串去重 15.数组中计算两数之和 16.数字到字符…...
vue2语法速通
首先,git clone下来的项目要npm install下载依赖,如果是vue项目,运行通常npm run serve或者npm run dev vue速通一下 使用vite创建项目(较快) npm create vite 配置文件 src/ ├── assets/ # 存放…...
LabVIEW图片识别逆向建模系统
本文介绍了一个基于LabVIEW的图片识别逆向建模系统的开发过程。系统利用LabVIEW的强大视觉处理功能,通过二维图片快速生成对应的三维模型,不仅降低了逆向建模的技术门槛,还大幅提升了建模效率。 项目背景 在传统的逆向建模过程中…...
idea隐藏无关文件
idea隐藏无关文件 如果你想隐藏某些特定类型的文件(例如 .log 文件或 .tmp 文件),可以通过以下步骤设置: 打开设置 在菜单栏中选择 File > Settings(Windows/Linux)或 IntelliJ IDEA > Preference…...
Google C++ Style / 谷歌C++开源风格
文章目录 前言1. 头文件1.1 自给自足的头文件1.2 #define 防护符1.3 导入你的依赖1.4 前向声明1.5 内联函数1.6 #include 的路径及顺序 2. 作用域2.1 命名空间2.2 内部链接2.3 非成员函数、静态成员函数和全局函数2.4 局部变量2.5 静态和全局变量2.6 thread_local 变量 3. 类3.…...
猫眼Java开发面试题及参考答案(上)
详细介绍项目,像项目中如何用 Redis,用到 Redis 哪些数据类型,项目中遇到哪些问题,怎么解决的 在我参与的一个电商项目中,Redis 发挥了至关重要的作用。这个电商项目主要是为用户提供商品浏览、购物车管理、订单处理等一系列功能。 在项目中使用 Redis 主要是为了提升系统…...
CNN的各种知识点(五):平均精度均值(mean Average Precision, mAP)
平均精度均值(mean Average Precision, mAP) 1. 平均精度均值(mean Average Precision, mAP)概念:计算步骤:具体例子:重要说明:典型值范围: 总结: 1. 平均精度…...
8.原型模式(Prototype)
动机 在软件系统中,经常面临着某些结构复杂的对象的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是它们却拥有比较稳定一致的接口。 之前的工厂方法和抽象工厂将抽象基类和具体的实现分开。原型模式也差不多&#…...
DeepSeek-R1:开源机器人智能控制系统的革命性突破
目录 引言 一、DeepSeek-R1 的概述 1.1 什么是 DeepSeek-R1? 1.2 DeepSeek-R1 的定位 二、DeepSeek-R1 的核心特性 2.1 实时控制能力 2.2 多传感器融合 2.3 路径规划与导航 2.4 人工智能集成 2.5 开源与模块化设计 2.6 跨平台支持 三、DeepSeek-R1 的技术…...
网络安全学习 day5
状态检测和会话技术 状态检测以 “ 数据流量 ” 为单位来对报文进行检测和转发。即对一条流量的第一个报文进行包过滤规 则检查,并将判断结果作为这条流量的 “ 状态 ” 记录下来 。对于该条流量的后续报文,直接根据这个 “ 状态 ”来判断是否转发还是…...
[leetcode·回溯算法]回溯算法解题套路框架
本文参考labuladong算法笔记[回溯算法解题套路框架 | labuladong 的算法笔记] 本文解决几个问题: 回溯算法是什么?解决回溯算法相关的问题有什么技巧?如何学习回溯算法?回溯算法代码是否有规律可循? 其实回溯算法和我…...
【怎么用系列】短视频戒除—1—对推荐算法进行干扰
如今推荐算法已经渗透到人们生活的方方面面,尤其是抖音等短视频核心就是推荐算法。 【短视频的危害】 1> 会让人变笨,慢慢让人丧失注意力与专注力 2> 让人丧失阅读长文的能力 3> 让人沉浸在一个又一个快感与嗨点当中。当我们刷短视频时&#x…...
【deepseek实战】绿色好用,不断网
前言 最佳deepseek火热网络,我也开发一款windows的电脑端,接入了deepseek,基本是复刻了网页端,还加入一些特色功能。 助力国内AI,发出自己的热量 说一下开发过程和内容的使用吧。 目录 一、介绍 二、具体工作 1.1、引…...
kali下Docker详细安装、docker-compose安装
目录 一、kali下docker安装 1. 更换apt源 2.安装docker 3.配置国内镜像加速器 4.利用docker运行靶场环境 二、docker-compose安装 1.下载docker-compose文件 2.将下载的文件复制到指定位置 3.赋予执行权限 4.利用docker-compose运行靶场环境 一、kali下docker安装 1.…...
Spring理论知识(Ⅴ)——Spring Web模块
Spring的组成 Spring由20个核心依赖组成,这20个核心依赖可以分为6个核心模块 Spring Web模块简介 众所周知,Java目前最大的一个用途就是作为Web应用的服务端(Java Web) Spring又是JavaEE中使用最广泛的开发框架࿰…...
图书管理系统 Axios 源码__新增图书
目录 功能介绍 核心代码解析 源码:新增图书功能 总结 本项目基于 HTML、Bootstrap、JavaScript 和 Axios 开发,实现了图书的增删改查功能。以下是新增图书的功能实现,适合前端开发学习和项目实践。 功能介绍 用户可以通过 模态框…...
【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】从计算机基础到HTML开发:Web开发的第一步
会议官网:www.acvra.org 简介 2025年计算机视觉研究进展与应用(ACVRA 2025)将于2025年2月28-3月2日在中国广州召开,将汇聚世界各地的顶尖学者、研究人员和行业专家,聚焦计算机视觉领域的最新研究动态与应用成就。本次…...
Med-R2:基于循证医学的检索推理框架:提升大语言模型医疗问答能力的新方法
Med-R2 : Crafting Trustworthy LLM Physicians through Retrieval and Reasoning of Evidence-Based Medicine Med-R2框架Why - 这个研究要解决什么现实问题What - 核心发现或论点是什么How - 1. 前人研究的局限性How - 2. 你的创新方法/视角How - 3. 关键数据支持How - 4. 可…...
Docker入门篇(Docker基础概念与Linux安装教程)
目录 一、什么是Docker、有什么作用 二、Docker与虚拟机(对比) 三、Docker基础概念 四、CentOS安装Docker 一、从零认识Docker、有什么作用 1.项目部署可能的问题: 大型项目组件较多,运行环境也较为复杂,部署时会碰到一些问题࿱…...
完美世界C++游戏开发面试题及参考答案
堆栈数据结构有什么区别,举例说明 栈(Stack)和堆(Heap)是两种不同的数据结构,它们在多个方面存在显著区别: 存储方式 栈:栈是一种后进先出(LIFO)的数据结构,它的存储空间是连续的。栈由系统自动分配和释放,用于存储函数调用时的局部变量、函数参数、返回地址等信息…...
【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.21 随机数生成:梅森旋转算法的工程实现
2.21 随机数生成:梅森旋转算法的工程实现 目录 #mermaid-svg-J92AWLtQsj9ys1z6 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-J92AWLtQsj9ys1z6 .error-icon{fill:#552222;}#mermaid-svg-J92AWLtQsj9y…...
LeetCode 0922.按奇偶排序数组 II:O(1)空间复杂度-一次遍历双指针
【LetMeFly】922.按奇偶排序数组 II:O(1)空间复杂度-一次遍历双指针 力扣题目链接:https://leetcode.cn/problems/sort-array-by-parity-ii/ 给定一个非负整数数组 nums, nums 中一半整数是 奇数 ,一半整数是 偶数 。 对数组进…...
VSCode设置内容字体大小
1、打开VSCode软件,点击左下角的“图标”,选择“Setting”。 在命令面板中的Font Size处选择适合自己的字体大小。 2、对比Font Size值为14与20下的字体大小。...
【蓝桥杯】日志统计
日志统计(编程题)https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53 题目 日志统计(编程题) 讲解 这个讲解感觉比较通俗易懂。 蓝桥杯2018年省赛B组08(c/c)日…...
九. Redis 持久化-AOF(详细讲解说明,一个配置一个说明分析,步步讲解到位 2)
九. Redis 持久化-AOF(详细讲解说明,一个配置一个说明分析,步步讲解到位 2) 文章目录 九. Redis 持久化-AOF(详细讲解说明,一个配置一个说明分析,步步讲解到位 2)1. Redis 持久化 AOF 概述2. AOF 持久化流程3. AOF 的配置4. AOF 启…...
蓝桥杯备赛题目练习(一)
一. 口算练习题 ## 题目描述 王老师正在教简单算术运算。细心的王老师收集了 i 道学生经常做错的口算题,并且想整理编写成一份练习。 编排这些题目是一件繁琐的事情,为此他想用计算机程序来提高工作效率。王老师希望尽量减少输入的工作量,比…...
【Linux探索学习】第二十八弹——信号(下):信号在内核中的处理及信号捕捉详解
Linux学习笔记: https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言: 在前面我们已经学习了有关信号的一些基本的知识点,包括:信号的概念、信号产生和信号处理等,今天我们重…...
AI与SEO关键词的完美结合如何提升网站流量与排名策略
内容概要 在当今数字营销环境中,内容的成功不仅依赖于高质量的创作,还包括高效的关键词策略。AI与SEO关键词的结合,正是这一趋势的重要体现。 AI技术在SEO中的重要性 在数字营销领域,AI技术的引入为SEO策略带来了前所未有的变革。…...
《运维:技术的基石,服务的保障》
1. LVS(Linux Virtual Server):基于Linux内核的四层负载均衡解决方案 2. Bonding(链路聚合):物理网卡冗余与带宽叠加技术 3. RHEL(Red Hat Enterprise Linux):企业级Li…...
CSS Display属性完全指南
CSS Display属性完全指南 引言核心概念常用display值详解1. block(块级元素)2. inline(行内元素)3. inline-block(行内块级元素)4. flex(弹性布局)5. grid(网格布局&…...
【C++】STL——vector底层实现
目录 💕 1.vector三个核心 💕2.begin函数,end函数的实现(简单略讲) 💕3.size函数,capacity函数的实现 (简单略讲) 💕4.reserve函数实现 (细节…...
Docker Compose的使用
文章首发于我的博客:https://blog.liuzijian.com/post/docker-compose.html 目录 Docker Compose是什么Docker Compose安装Docker Compose文件Docker Compose常用命令案例:部署WordPress博客系统 Docker Compose是什么 Docker Compose是Docker官方的开源…...
11 3D变换模块(transform3d.rs)
transform3d.rs代码定义了一个名为 Transform3D 的 Rust 结构体,它用于表示一个3D变换矩阵。这个结构体是泛型的,包含三个类型参数:T、Src 和 Dst。其中,T 用于矩阵元素的数据类型,Src 和 Dst 用于表示变换的源和目标类…...
昆仑万维Java开发面试题及参考答案
进程和线程的区别是什么? 进程和线程都是操作系统中非常重要的概念,它们在多个方面存在显著的区别。 从定义上看,进程是操作系统进行资源分配和调度的基本单位。每个进程都有自己独立的内存空间,包括代码段、数据段、堆栈段等。例如,当你在电脑上同时打开浏览器和音乐播放…...
vscode命令面板输入 CMake:build不执行提示输入
CMake:build或rebuild不编译了,弹出:> [Add a new preset] , 提示输入发现settings.jsons设置有问题 { "workbench.colorTheme": "Default Light", "cmake.pinnedCommands": [ "workbench.action.tasks.configu…...
Fastdds学习分享_xtpes_发布订阅模式及rpc模式
在之前的博客中我们介绍了dds的大致功能,与组成结构。本篇博文主要介绍的是xtypes.分为理论和实际运用两部分.理论主要用于梳理hzy大佬的知识,对于某些一带而过的部分作出更为详细的阐释,并在之后通过实际案例便于理解。案例分为普通发布订阅…...
什么叫DeepSeek-V3,以及与GPT-4o的区别
1. DeepSeek 的故事 1.1 DeepSeek 是什么? DeepSeek 是一家专注于人工智能技术研发的公司,致力于打造高性能、低成本的 AI 模型。它的目标是让 AI 技术更加普惠,让更多人能够用上强大的 AI 工具。 1.2 DeepSeek-V3 的问世 DeepSeek-V3 是…...
【C#】Process、ProcessStartInfo启动外部exe
在C#中使用 Process 和 ProcessStartInfo 类启动外部 .exe 文件,可以按照以下步骤进行: 创建 ProcessStartInfo 实例:配置进程启动信息,包括可执行文件的路径、传递给该程序的参数等。 设置启动选项:根据需要配置 Pro…...