当前位置: 首页 > news >正文

【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

第一行是请求行,保存有关客户端请求的信息。请求行的第一部分指示正在使用的方法,例如GETPOST ,它描述了客户端如何发出此请求。我们的客户使用了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_linefilename的值。

试一下:

正常访问:
请添加图片描述

非正常访问:
请添加图片描述

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服务器

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 20.1.1. 什么是TCP和HTTP Web 服务器涉及的两个主要协议是超文本传输​​协议(Hypertext T…...

LabVIEW涡轮诊断系统

一、项目背景与行业痛点 涡轮机械是发电厂、航空发动机、石油化工等领域的核心动力设备&#xff0c;其运行状态直接关系到生产安全与经济效益。据统计&#xff0c;涡轮故障导致的非计划停机可造成每小时数十万元的经济损失&#xff0c;且突发故障可能引发严重安全事故。传统人…...

想品客老师的第十天:类

类是一个优化js面向对象的工具 类的声明 //1、class User{}console.log(typeof User)//function//2、let Hdclass{}//其实跟1差不多class Stu{show(){}//注意这里不用加逗号&#xff0c;对象才加逗号get(){console.log(后盾人)}}let hdnew Stu()hd.get()//后盾人 类的原理 类…...

注解(Annotation)

注解&#xff08;Annotation&#xff09;在 Java 中可以用来简化类的使用&#xff0c;使得被注解的类能够被自动发现、自动创建并在需要的地方直接调用&#xff0c;而不需要手动创建实例。具体来说&#xff0c;注解是用来标识类、方法、字段等的&#xff0c;它们通常与一些框架…...

使用开源项目:pdf2docx,让PDF转换为Word

目录 1.安装python 2.安装 pdf2docx 3.使用 pdf2docx 转换 PDF 到 Word pdf2docx&#xff1a;GitCode - 全球开发者的开源社区,开源代码托管平台 环境&#xff1a;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应用时&#xff0c;我们经常需要处理一些敏感的配置信息&#xff0c;比如数据库密码、API密钥等。以下是一个最佳实践方案&#xff1a; 1. 创建配置文件 application.yml&#xff08;版本控制&#xff09; spring:datasource:url: ${MYSQL_URL:jdbc:mysql…...

为AI聊天工具添加一个知识系统 之77 详细设计之18 正则表达式 之5

本文要点 昨天讨论了 本项目&#xff08;AI聊天工具添加一个知识系统&#xff09;中正则表达式模板的设计中可能要考虑到的一些问题&#xff08;讨论到的内容比较随意&#xff0c;暂时无法确定 那些考虑 是否 应该是正则表达式模板设计要考虑的以及 是否完整&#xff09;。今天…...

Ubuntu下Tkinter绑定数字小键盘上的回车键(PySide6类似)

设计了一个tkinter程序&#xff0c;在Win下绑定回车键&#xff0c;直接绑定"<Return>"就可以使用主键盘和小键盘的回车键直接“提交”&#xff0c;到了ubuntu下就不行了。经过搜索&#xff0c;发现ubuntu下主键盘和数字小键盘的回车键&#xff0c;名称不一样。…...

安全实验作业

一 拓扑图 二 要求 1、R4为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4与其他所有直连设备间均使用共有IP 2、R3-R5-R6-R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 4、所有设备均可访问R4的环回&#x…...

NOTEPAD++编写abap

参考下面三个链接 Notepad ABAP代码高亮显示_notepad代码高亮颜色-CSDN博客 百度安全验证 ABAP Syntax Highlighting in Notepad Part 2 - SAP Community 最后XML文件看看你可以自己增加些新语法的高亮显示...

基于python的体育新闻数据可视化及分析

项目 &#xff1a;北京冬奥会体育新闻数据可视化及分析 摘 要 随着社会的不断进步与发展&#xff0c;新时代下的网络媒体获取的信息也更加庞大和繁杂&#xff0c;相比于传统信息来源更加难以分析和辨别&#xff0c;造成了新时代媒体从业者撰写新闻的难度。在此背景下&#xff…...

C# 精炼题18道题(类,三木运算,Switch,计算器)

1.数组元素和 2.数组元素乘积 3.数组元素平均数 4.数组中最大值 5.数组中的偶数 6.数组中的阶乘 7.数组反转 8.字符串反转 9.回文字符串 10.检查回文 11.最小最大值 12.找素数 13.字符串中的最长无重复字符串 14.字符串去重 15.数组中计算两数之和 16.数字到字符…...

vue2语法速通

首先&#xff0c;git clone下来的项目要npm install下载依赖&#xff0c;如果是vue项目&#xff0c;运行通常npm run serve或者npm run dev vue速通一下 使用vite创建项目&#xff08;较快&#xff09; npm create vite 配置文件 src/ ├── assets/ # 存放…...

LabVIEW图片识别逆向建模系统

本文介绍了一个基于LabVIEW的图片识别逆向建模系统的开发过程。系统利用LabVIEW的强大视觉处理功能&#xff0c;通过二维图片快速生成对应的三维模型&#xff0c;不仅降低了逆向建模的技术门槛&#xff0c;还大幅提升了建模效率。 ​ 项目背景 在传统的逆向建模过程中&#xf…...

idea隐藏无关文件

idea隐藏无关文件 如果你想隐藏某些特定类型的文件&#xff08;例如 .log 文件或 .tmp 文件&#xff09;&#xff0c;可以通过以下步骤设置&#xff1a; 打开设置 在菜单栏中选择 File > Settings&#xff08;Windows/Linux&#xff09;或 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)

平均精度均值&#xff08;mean Average Precision, mAP&#xff09; 1. 平均精度均值&#xff08;mean Average Precision, mAP&#xff09;概念&#xff1a;计算步骤&#xff1a;具体例子&#xff1a;重要说明&#xff1a;典型值范围&#xff1a; 总结&#xff1a; 1. 平均精度…...

8.原型模式(Prototype)

动机 在软件系统中&#xff0c;经常面临着某些结构复杂的对象的创建工作&#xff1b;由于需求的变化&#xff0c;这些对象经常面临着剧烈的变化&#xff0c;但是它们却拥有比较稳定一致的接口。 之前的工厂方法和抽象工厂将抽象基类和具体的实现分开。原型模式也差不多&#…...

DeepSeek-R1:开源机器人智能控制系统的革命性突破

目录 引言 一、DeepSeek-R1 的概述 1.1 什么是 DeepSeek-R1&#xff1f; 1.2 DeepSeek-R1 的定位 二、DeepSeek-R1 的核心特性 2.1 实时控制能力 2.2 多传感器融合 2.3 路径规划与导航 2.4 人工智能集成 2.5 开源与模块化设计 2.6 跨平台支持 三、DeepSeek-R1 的技术…...

网络安全学习 day5

状态检测和会话技术 状态检测以 “ 数据流量 ” 为单位来对报文进行检测和转发。即对一条流量的第一个报文进行包过滤规 则检查&#xff0c;并将判断结果作为这条流量的 “ 状态 ” 记录下来 。对于该条流量的后续报文&#xff0c;直接根据这个 “ 状态 ”来判断是否转发还是…...

[leetcode·回溯算法]回溯算法解题套路框架

本文参考labuladong算法笔记[回溯算法解题套路框架 | labuladong 的算法笔记] 本文解决几个问题&#xff1a; 回溯算法是什么&#xff1f;解决回溯算法相关的问题有什么技巧&#xff1f;如何学习回溯算法&#xff1f;回溯算法代码是否有规律可循&#xff1f; 其实回溯算法和我…...

【怎么用系列】短视频戒除—1—对推荐算法进行干扰

如今推荐算法已经渗透到人们生活的方方面面&#xff0c;尤其是抖音等短视频核心就是推荐算法。 【短视频的危害】 1> 会让人变笨&#xff0c;慢慢让人丧失注意力与专注力 2> 让人丧失阅读长文的能力 3> 让人沉浸在一个又一个快感与嗨点当中。当我们刷短视频时&#x…...

【deepseek实战】绿色好用,不断网

前言 最佳deepseek火热网络&#xff0c;我也开发一款windows的电脑端&#xff0c;接入了deepseek&#xff0c;基本是复刻了网页端&#xff0c;还加入一些特色功能。 助力国内AI&#xff0c;发出自己的热量 说一下开发过程和内容的使用吧。 目录 一、介绍 二、具体工作 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个核心依赖组成&#xff0c;这20个核心依赖可以分为6个核心模块 Spring Web模块简介 众所周知&#xff0c;Java目前最大的一个用途就是作为Web应用的服务端&#xff08;Java Web&#xff09; Spring又是JavaEE中使用最广泛的开发框架&#xff0…...

图书管理系统 Axios 源码__新增图书

目录 功能介绍 核心代码解析 源码&#xff1a;新增图书功能 总结 本项目基于 HTML、Bootstrap、JavaScript 和 Axios 开发&#xff0c;实现了图书的增删改查功能。以下是新增图书的功能实现&#xff0c;适合前端开发学习和项目实践。 功能介绍 用户可以通过 模态框&#xf…...

【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】从计算机基础到HTML开发:Web开发的第一步

会议官网&#xff1a;www.acvra.org 简介 2025年计算机视觉研究进展与应用&#xff08;ACVRA 2025&#xff09;将于2025年2月28-3月2日在中国广州召开&#xff0c;将汇聚世界各地的顶尖学者、研究人员和行业专家&#xff0c;聚焦计算机视觉领域的最新研究动态与应用成就。本次…...

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.项目部署可能的问题&#xff1a; 大型项目组件较多&#xff0c;运行环境也较为复杂&#xff0c;部署时会碰到一些问题&#xff1…...

完美世界C++游戏开发面试题及参考答案

堆栈数据结构有什么区别,举例说明 栈(Stack)和堆(Heap)是两种不同的数据结构,它们在多个方面存在显著区别: 存储方式 栈:栈是一种后进先出(LIFO)的数据结构,它的存储空间是连续的。栈由系统自动分配和释放,用于存储函数调用时的局部变量、函数参数、返回地址等信息…...

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】2.21 随机数生成:梅森旋转算法的工程实现

2.21 随机数生成&#xff1a;梅森旋转算法的工程实现 目录 #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&#xff1a;O(1)空间复杂度-一次遍历双指针 力扣题目链接&#xff1a;https://leetcode.cn/problems/sort-array-by-parity-ii/ 给定一个非负整数数组 nums&#xff0c; nums 中一半整数是 奇数 &#xff0c;一半整数是 偶数 。 对数组进…...

VSCode设置内容字体大小

1、打开VSCode软件&#xff0c;点击左下角的“图标”&#xff0c;选择“Setting”。 在命令面板中的Font Size处选择适合自己的字体大小。 2、对比Font Size值为14与20下的字体大小。...

【蓝桥杯】日志统计

日志统计&#xff08;编程题&#xff09;https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53https://dashoj.com/d/lqbproblem/p/53 题目 日志统计(编程题) 讲解 这个讲解感觉比较通俗易懂。 蓝桥杯2018年省赛B组08&#xff08;c/c&#xff09;日…...

九. Redis 持久化-AOF(详细讲解说明,一个配置一个说明分析,步步讲解到位 2)

九. Redis 持久化-AOF(详细讲解说明&#xff0c;一个配置一个说明分析&#xff0c;步步讲解到位 2) 文章目录 九. Redis 持久化-AOF(详细讲解说明&#xff0c;一个配置一个说明分析&#xff0c;步步讲解到位 2)1. Redis 持久化 AOF 概述2. AOF 持久化流程3. AOF 的配置4. AOF 启…...

蓝桥杯备赛题目练习(一)

一. 口算练习题 ## 题目描述 王老师正在教简单算术运算。细心的王老师收集了 i 道学生经常做错的口算题&#xff0c;并且想整理编写成一份练习。 编排这些题目是一件繁琐的事情&#xff0c;为此他想用计算机程序来提高工作效率。王老师希望尽量减少输入的工作量&#xff0c;比…...

【Linux探索学习】第二十八弹——信号(下):信号在内核中的处理及信号捕捉详解

Linux学习笔记&#xff1a; https://blog.csdn.net/2301_80220607/category_12805278.html?spm1001.2014.3001.5482 前言&#xff1a; 在前面我们已经学习了有关信号的一些基本的知识点&#xff0c;包括&#xff1a;信号的概念、信号产生和信号处理等&#xff0c;今天我们重…...

AI与SEO关键词的完美结合如何提升网站流量与排名策略

内容概要 在当今数字营销环境中&#xff0c;内容的成功不仅依赖于高质量的创作&#xff0c;还包括高效的关键词策略。AI与SEO关键词的结合&#xff0c;正是这一趋势的重要体现。 AI技术在SEO中的重要性 在数字营销领域&#xff0c;AI技术的引入为SEO策略带来了前所未有的变革。…...

《运维:技术的基石,服务的保障》

1. LVS&#xff08;Linux Virtual Server&#xff09;&#xff1a;基于Linux内核的四层负载均衡解决方案 2. Bonding&#xff08;链路聚合&#xff09;&#xff1a;物理网卡冗余与带宽叠加技术 3. RHEL&#xff08;Red Hat Enterprise Linux&#xff09;&#xff1a;企业级Li…...

CSS Display属性完全指南

CSS Display属性完全指南 引言核心概念常用display值详解1. block&#xff08;块级元素&#xff09;2. inline&#xff08;行内元素&#xff09;3. inline-block&#xff08;行内块级元素&#xff09;4. flex&#xff08;弹性布局&#xff09;5. grid&#xff08;网格布局&…...

【C++】STL——vector底层实现

目录 &#x1f495; 1.vector三个核心 &#x1f495;2.begin函数&#xff0c;end函数的实现&#xff08;简单略讲&#xff09; &#x1f495;3.size函数&#xff0c;capacity函数的实现 &#xff08;简单略讲&#xff09; &#x1f495;4.reserve函数实现 &#xff08;细节…...

Docker Compose的使用

文章首发于我的博客&#xff1a;https://blog.liuzijian.com/post/docker-compose.html 目录 Docker Compose是什么Docker Compose安装Docker Compose文件Docker Compose常用命令案例&#xff1a;部署WordPress博客系统 Docker Compose是什么 Docker Compose是Docker官方的开源…...

11 3D变换模块(transform3d.rs)

transform3d.rs代码定义了一个名为 Transform3D 的 Rust 结构体&#xff0c;它用于表示一个3D变换矩阵。这个结构体是泛型的&#xff0c;包含三个类型参数&#xff1a;T、Src 和 Dst。其中&#xff0c;T 用于矩阵元素的数据类型&#xff0c;Src 和 Dst 用于表示变换的源和目标类…...

昆仑万维Java开发面试题及参考答案

进程和线程的区别是什么? 进程和线程都是操作系统中非常重要的概念,它们在多个方面存在显著的区别。 从定义上看,进程是操作系统进行资源分配和调度的基本单位。每个进程都有自己独立的内存空间,包括代码段、数据段、堆栈段等。例如,当你在电脑上同时打开浏览器和音乐播放…...

vscode命令面板输入 CMake:build不执行提示输入

CMake&#xff1a;build或rebuild不编译了&#xff0c;弹出:> [Add a new preset] , 提示输入发现settings.jsons设置有问题 { "workbench.colorTheme": "Default Light", "cmake.pinnedCommands": [ "workbench.action.tasks.configu…...

Fastdds学习分享_xtpes_发布订阅模式及rpc模式

在之前的博客中我们介绍了dds的大致功能&#xff0c;与组成结构。本篇博文主要介绍的是xtypes.分为理论和实际运用两部分.理论主要用于梳理hzy大佬的知识&#xff0c;对于某些一带而过的部分作出更为详细的阐释&#xff0c;并在之后通过实际案例便于理解。案例分为普通发布订阅…...

什么叫DeepSeek-V3,以及与GPT-4o的区别

1. DeepSeek 的故事 1.1 DeepSeek 是什么&#xff1f; DeepSeek 是一家专注于人工智能技术研发的公司&#xff0c;致力于打造高性能、低成本的 AI 模型。它的目标是让 AI 技术更加普惠&#xff0c;让更多人能够用上强大的 AI 工具。 1.2 DeepSeek-V3 的问世 DeepSeek-V3 是…...

【C#】Process、ProcessStartInfo启动外部exe

在C#中使用 Process 和 ProcessStartInfo 类启动外部 .exe 文件&#xff0c;可以按照以下步骤进行&#xff1a; 创建 ProcessStartInfo 实例&#xff1a;配置进程启动信息&#xff0c;包括可执行文件的路径、传递给该程序的参数等。 设置启动选项&#xff1a;根据需要配置 Pro…...