如何实现 在控制台上输入“exit”命令进行清理。
或打开“ http://127.0.0.1:8080/terminal”进行清理。
完整源码
main.rs
mod lib;
use std::net::{TcpStream, TcpListener};
use std::io::{Read, Write};
use std::fs;
use std::thread;
use std::time::Duration;
use lib::ThreadPool;
use std::sync::{Arc, Mutex};
fn main() {
let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
{
let thread_pool = ThreadPool::new(4);
for stream in listener.incoming().take(4) {
let stream = stream.unwrap();
// thread::spawn(|| {
// handler_connection(stream);
// });
thread_pool.execute(|| {
handler_connection(stream);
})
}
}
println!("Shutting down.");
}
fn handler_connection(mut stream: TcpStream,) {
let mut buffer = vec![0; 1024];
stream.read(&mut buffer).unwrap();
let header = String::from_utf8_lossy(&buffer);
// println!("buffer\n{}", header);
let (file_name, status, ) =
if header.starts_with("GET /terminal HTTP/1.1") {
("./terminal.html", "200 OK")
} else if header.starts_with("GET /sleep HTTP/1.1") {
thread::sleep(Duration::from_secs(5));
("./sleep.html", "200 OK")
} else if header.starts_with("GET / HTTP/1.1") {
("./hello.html", "200 OK")
} else {
("./404.html", "404 NOT FOUND")
};
let file_content = fs::read_to_string(file_name).unwrap();
let response = format!("HTTP/1.1 {}\r\nConnect-length:{}\r\n\r\n{}",
status, file_content.len(), file_content);
stream.write(response.as_bytes()).unwrap();
stream.flush().unwrap();
}
lib.rs
use std::thread;
use std::sync::{mpsc, Mutex, Arc,};
type Job = Box<dyn FnOnce() + Send + 'static>;
enum Message {
NewJob(Job),
Terminate,
}
pub struct ThreadPool {
workers: Vec<Worker>,
sender: mpsc::Sender<Message>,
}
impl ThreadPool {
pub fn new(size:usize) -> ThreadPool {
assert!(size > 0);
let (sender, receiver) = mpsc::channel();
let locker = Mutex::new(receiver);
let arc_locker = Arc::new(locker);
let mut workers = Vec::with_capacity(size);
for id in 0..size {
workers.push(Worker::new(id, Arc::clone(&arc_locker)),);
}
ThreadPool {
workers,
sender: sender,
}
}
pub fn execute<F>(&self, f: F)
where F: FnOnce() + Send + 'static {
let job = Box::new(f);
let message = Message::NewJob(job);
match self.sender.send(message) {
Ok(_) => {
},
Err(e) => {
panic!("error:\n{}", e)
}
}
}
}
struct Worker {
id: usize,
thread: Option<thread::JoinHandle<()>>,
}
impl Worker {
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {
let thread = thread::spawn(move || {
while let Ok(message) = {
let x = receiver.lock().unwrap().recv();
x
} {
let v = Worker::execute_message(id, message);
if v == true {
break;
}
}
});
Worker {
id,
thread: Some(thread),
}
}
fn execute_message(id:usize, message: Message) -> bool {
match message {
Message::NewJob(job) => {
println!("Worker {} got a job; executing.", id);
job();
false
},
Message::Terminate => {
println!("Worker {} was told to terminate.", id);
true
}
}
}
}
impl Drop for ThreadPool {
fn drop(&mut self) {
for _ in &self.workers {
self.sender.send(Message::Terminate).unwrap();
}
for worker in &mut self.workers {
println!("Shutting down worker {}", worker.id);
if let Some(thread) = worker.thread.take() {
thread.join().unwrap();
}
}
}
}
1
共 2 条评论, 1 页
评论区
写评论解决好了,一晃快2年过去了。Chatgpt真恐怖感觉真的有一个人在旁边实时的教你怎么写代码。
https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=def34d2beba99897c03e147ae345f927
--
👇
viruscamp: 是的,官方教程其实只是线程池的 drop ,只能“在处理两个请求之后通过退出循环来停止 server”。
建议你自己试着实现你提的功能,提示是独立线程中的 accept 循环,主线程中的监控循环。
不行的话再看看我的实现 进化的 Http Server : 一 多线程正确停机
是的,官方教程其实只是线程池的 drop ,只能“在处理两个请求之后通过退出循环来停止 server”。
建议你自己试着实现你提的功能,提示是独立线程中的 accept 循环,主线程中的监控循环。
不行的话再看看我的实现 进化的 Http Server : 一 多线程正确停机