https://www.cnblogs.com/skzxc/p/12129353.html
默认已经安装好MSVC。
官网https://www.rust-lang.org/zh-CN/learn/get-started安装Rust安装器,选择winodwsx64版本
运行安装,将文件夹移动到D盘,安装后,文件夹在C:\\Users\\xxx下有.cargo和.rustup两个文件夹
新建环境变量
CARGO_HOME
D:\\Users\\xxx\\.cargo
RUSTUP_HOME
D:\\Users\\xxx\\.rustup
path
%CARGO_HOME%\\bin
测试安装成功,输入命令
cargo –version
rustup –version
环境变量配置加速安装地址
RUSTUP_DIST_SERVER
https://mirrors.tuna.tsinghua.edu.cn/rustup
RUSTUP_UPDATE_ROOT
https://mirrors.tuna.tsinghua.edu.cn/rustup/rustup
配置库镜像,在C:\\Users\\xxx\\.cargo下创建config.toml文件,无后缀,复制粘贴
[source.crates-io]
registry = "https://github.com/rust-lang/crates.io-index"
replace-with = "tuna"
[source.tuna]
registry = "https://mirrors.tuna.tsinghua.edu.cn/git/crates.io-index.git"
运行安装程序。
安装VSCode插件
- Rust Analyzer
- Even Better TOML
- CodeLLDB
开发示例
下面包含给出一个Rust服务器的开发示例
给出需求:
开发步骤:
新建一个项目,命令行输入cargo new myproject
测试环境配置,编译cargo build
测试环境配置,运行cargo run
cargo.toml中,复制粘贴
[package]
name = "mini_server"
version = "0.1.0"
edition = "2024"
[dependencies]
hyper = { version = "0.14", features = ['full']}
tokio = { version = "1", features = ["full"] }
url = '2.3'
mime_guess = "2.0"
src/main.rs中,复制粘贴
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Method, Request, Response, Server, StatusCode};
use std::fs;
use std::net::SocketAddr;
use std::path::Path;
use std::sync::Arc;
use tokio::signal;
use hyper::body::to_bytes;
use url::form_urlencoded;
use mime_guess::from_path;
#[tokio::main]
async fn main() {
// 从命令行参数获取HTML文件路径和端口号
let args: Vec<String> = std::env::args().collect();
let html_file_path = args.get(1).map(|s| s.as_str()).unwrap_or("index.html");
let port = args.get(2).and_then(|s| s.parse::<u16>().ok()).unwrap_or(8787);
// 检查文件是否存在
if !Path::new(html_file_path).exists() {
eprintln!("File not found: {}", html_file_path);
return;
}
// 将HTML文件路径存储在Arc中以便在多个请求之间共享
let html_file_path = Arc::new(html_file_path.to_string());
// 定义服务处理函数
let make_svc = make_service_fn(move |_conn| {
let html_file_path = Arc::clone(&html_file_path);
async move {
Ok::<_, hyper::Error>(service_fn(move |req| {
let html_file_path = Arc::clone(&html_file_path);
async move {
handle_request(req, html_file_path).await
}
}))
}
});
// 定义服务器地址
let addr = SocketAddr::from(([127, 0, 0, 1], port));
// 启动服务器
let server = Server::bind(&addr).serve(make_svc);
// 处理服务器关闭信号
let graceful = server.with_graceful_shutdown(shutdown_signal());
println!("Server running at http://{}", addr);
// 运行服务器
if let Err(e) = graceful.await {
eprintln!("Server error: {}", e);
}
}
// 处理HTTP请求
async fn handle_request(
req: Request<Body>,
html_file_path: Arc<String>,
) -> Result<Response<Body>, hyper::Error> {
match (req.method(), req.uri().path()) {
// 返回HTML内容
(&Method::GET, "/") => {
match read_file_to_string(&html_file_path) {
Ok(content) => Ok(Response::new(Body::from(content))),
Err(e) => {
let response = Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Body::from(format!("Failed to read HTML file: {}", e)))
.unwrap(); // This unwrap is safe because we know the builder is correctly configured
Ok(response)
}
}
}
// 处理文件写入请求
(&Method::POST, "/write") => {
// 解析查询参数
let query = req.uri().query().unwrap_or_default();
let params: Vec<(String, String)> = form_urlencoded::parse(query.as_bytes())
.into_owned()
.collect();
// 获取文件路径参数
let file_path = params
.iter()
.find(|(key, _)| key == "filepath")
.map(|(_, value)| value.to_string())
.unwrap_or_else(|| "example.txt".to_string());
// 读取请求体内容
let body_bytes = to_bytes(req.into_body()).await?;
let body_content = String::from_utf8(body_bytes.to_vec()).unwrap_or_default();
// 写入文件
match write_string_to_file(&file_path, &body_content) {
Ok(_) => Ok(Response::new(Body::from("File written successfully"))),
Err(e) => {
let response = Response::builder()
.status(StatusCode::INTERNAL_SERVER_ERROR)
.body(Body::from(format!("Failed to write file: {}", e)))
.unwrap(); // This unwrap is safe because we know the builder is correctly configured
Ok(response)
}
}
}
(&Method::GET, path) => {
// 构建文件路径
let file_path = format!(".{}", path);
match read_file_to_bytes(&file_path) {
Ok(content) => {
// 根据文件扩展名猜测MIME类型
let mime_type = from_path(&file_path).first_or_octet_stream();
let response = Response::builder()
.header("Content-Type", mime_type.as_ref())
.body(Body::from(content))
.unwrap(); // This unwrap is safe because we know the builder is correctly configured
Ok(response)
}
Err(_) => {
// 文件不存在,返回404 Not Found
let response = Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("Not Found"))
.unwrap(); // This unwrap is safe because we know the builder is correctly configured
Ok(response)
}
}
}
// 返回404 Not Found
_ => {
let response = Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::from("Not Found"))
.unwrap(); // This unwrap is safe because we know the builder is correctly configured
Ok(response)
}
}
}
// 处理服务器关闭信号
async fn shutdown_signal() {
// 等待Ctrl+C信号
signal::ctrl_c()
.await
.expect("Failed to install CTRL+C signal handler");
println!("Shutting down server…");
}
// 读取文件内容为字符串
fn read_file_to_string(file_path: &str) -> Result<String, std::io::Error> {
fs::read_to_string(file_path)
}
// 将字符串写入文件
fn write_string_to_file(file_path: &str, content: &str) -> Result<(), std::io::Error> {
fs::write(file_path, content)
}
// 读取文件内容为字节数组
fn read_file_to_bytes(file_path: &str) -> Result<Vec<u8>, std::io::Error> {
fs::read(file_path)
}
cargo build。让大模型生成一个index.html文件,与生成的exe放进文件夹,点击运行即可。
评论前必须登录!
注册