use std::net::TcpListener;
use std::net::TcpStream;
use std::io::Read;
use std::io::Write;
use std::fs;
use std::time::Duration;
use std::thread;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
pub structThreadPool{
workers:Vec<Worker>,
sender:mpsc::Sender<Message>,}
type Job =Box<dyn FnOnce()+Send +'static>;//Box 存储的是闭包//为了程序退出,必须通过闭包的形式通知enumMessage{NewJob(Job),//执行仍无,闭包
Terminate,//退出消息}
impl ThreadPool{
pub fn new(size:usize)->ThreadPool{
assert!(size>0);//创建通道(队列)let(sender,receiver)= mpsc::channel();
let receiver =Arc::new(Mutex::new(receiver));//创建work,然后保存到workers
let mut workers =Vec::with_capacity(size);for id in 0..size{
workers.push(Worker::new(id,Arc::clone(&receiver)));}
ThreadPool{workers,sender}}
pub fn execute<F>(&self,f:F)
where
F:FnOnce()+Send +'static,{
let job =Box::new(f);
self.sender.send(Message::NewJob(job)).unwrap();}}
impl Drop for ThreadPool{
fn drop(&mut self){
println!("drop ThreadPool");//1怎么通知线程退出,之前c把某个线程置位//发送一个退出的消息for _ in & self.workers{
self.sender.send(Message::Terminate).unwrap();}//2 等待所有线程退出
println!("wait work terminate...");// for worker in &mut self.workers{// println!("work {} shutdown...",worker.id);// worker.thread.join().unwrap();// }for worker in &mut self.workers{
println!("work {} shutdown...",worker.id);if let Some(thread)= worker.thread.take(){//take取出所有权
thread.join().unwrap();}}}}//封装线程structWorker{
id:usize,// thread:thread::JoinHandle<()>,
thread:Option<thread::JoinHandle<()>>,}
impl Worker{
pub fn new(id:usize,receiver:Arc<Mutex<mpsc::Receiver<Message>>>)->Worker{
let thread1 = thread::spawn(move ||loop{
let message = receiver.lock().unwrap().recv().unwrap();
match message{Message::NewJob(job)=>{
println!("work:{},get a job",id);job();},
Message::Terminate =>{
println!("work:{}was told to terminate",id);break;}}});
Worker{id,thread:Some(thread1)}//此处名字与Worker里要一致}}
fn main(){
let listener =TcpListener::bind("0.0.0.0:3333").unwrap();
println!("bind ok and listen port 3333");
let pool =ThreadPool::new(4);//线程池for stream in listener.incoming().take(2){//take(2)运行两次退出可以去掉
match stream{Ok(stream)=>{
println!("new connect");
pool.execute(||{//传闭包handle_connectuin(stream);});},Err(e)=>{
println!("Error:{:?}",e);}}}drop(pool);}//读取消息
fn handle_connectuin(mut stream:TcpStream){
let mut buffer =[0 as u8;1024];
stream.read(&mut buffer).unwrap();// println!("req:{}",String::from_utf8_lossy(&buffer[..]));//匹配get ///匹配get /hello
let get = b"GET / HTTP/1.1\r\n";
let get_sleep = b"GET /sleep HTTP/1.1\r\n";if buffer.starts_with(get){//读取文件
let contents = fs::read_to_string("hello.txt").unwrap();//回复客户端
let responese = format!("HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}",
contents.len(),
contents
);// let responese ="HTTP/1.1 200 OK\r\n\r\nwanying";
stream.write(responese.as_bytes()).unwrap();
stream.flush().unwrap();}elseif buffer.starts_with(get_sleep){
thread::sleep(Duration::from_secs(20));//读取文件
let contents = fs::read_to_string("sleep.txt").unwrap();//回复客户端
let responese = format!("HTTP/1.1 200 OK\r\nContent-Length: {}\r\n\r\n{}",
contents.len(),
contents
);// let responese ="HTTP/1.1 200 OK\r\n\r\nwanying";
stream.write(responese.as_bytes()).unwrap();
stream.flush().unwrap();}else{//读取文件
let contents = fs::read_to_string("404.txt").unwrap();//回复客户端
let responese = format!("HTTP/1.1 404 NOT FOUND\r\nContent-Length: {}\r\n\r\n{}",
contents.len(),
contents
);// let responese ="HTTP/1.1 200 OK\r\n\r\nwanying";// println!("rep:{}",responese);
stream.write(responese.as_bytes()).unwrap();
stream.flush().unwrap();}}