Rust webserver服务


Rust 的简单的webserever服务。
编写参考于令狐一冲的视频。

一、单线程服务

use std::net::TcpListener;
use std::net::TcpStream;
use std::io::{Read, Write};
use std::fs;

fn handle_client(mut stream:TcpStream){
    let mut buffer = [1;512];
    stream.read(&mut buffer).unwrap();
    println!("收到了请求!{:#?}",String::from_utf8_lossy(&buffer));


    // ===直接返回响应==
    // let response = "HTTP/1.1 200 OK\r\n\r\n";
    // stream.write(response.as_bytes()).unwrap();
    // stream.flush().unwrap();


    // ===返回网页===
    // let content = fs::read_to_string("./main.html").unwrap();
    // let response = format!("HTTP/1.1 200 OK\r\n\r\n {}",content);
    // stream.write(response.as_bytes()).unwrap();
    // stream.flush().unwrap();


    // ===有条件的返回网页===
    // let get = b"GET / HTTP/1.1\r\n";
    // if buffer.starts_with(get){
    //     let content = fs::read_to_string("./main.html").unwrap();
    //     let response = format!("HTTP/1.1 200 OK\r\n\r\n {}",content);
    //     stream.write(response.as_bytes()).unwrap();
    //     stream.flush().unwrap();
    // }else {
    //     let content = fs::read_to_string("./404.html").unwrap();
    //     let response = format!("HTTP/1.1 404 Not Found\r\n\r\n {}",content);
    //     stream.write(response.as_bytes()).unwrap();
    //     stream.flush().unwrap();
    // }

    // ===重构有条件的返回网页===
    let get = b"GET / HTTP/1.1\r\n";
    let (status_line ,filename) = if buffer.starts_with(get){
        ("HTTP/1.1 200 OK\r\n\r\n","main.html")
    }else {
        ("HTTP/1.1 404 Not Found\r\n\r\n","404.html")
    };
    let contents = fs::read_to_string(filename).unwrap();
    let response = format!("{}{}",status_line,contents);
    stream.write(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

fn main() -> std::io::Result<()>{
    let listener = TcpListener::bind("127.0.0.1:8080")?;


    for stream in listener.incoming(){
        handle_client(stream?);
    }
    println!("Hello, world!");

    Ok(())
}

二、使用线程池

main.rs

use std::net::TcpListener;
use std::net::TcpStream;
use std::io::{Read, Write};
use std::fs;
use std::thread;
use std::time;
use webserver_multi::ThreadPool;


fn handle_client(mut stream:TcpStream){
    let mut buffer = [1;512];
    stream.read(&mut buffer).unwrap();

    let get = b"GET / HTTP/1.1\r\n";
    let (status_line ,filename) = if buffer.starts_with(get){
        ("HTTP/1.1 200 OK\r\n\r\n","main.html")
    }else {
        ("HTTP/1.1 404 Not Found\r\n\r\n","404.html")
    };
    let contents = fs::read_to_string(filename).unwrap();
    let response = format!("{}{}",status_line,contents);

    let t0 = time::Duration::from_micros(500);
    thread::sleep(t0);           //休息一下,模拟工作

    stream.write(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

fn main() -> std::io::Result<()>{
    let listener = TcpListener::bind("127.0.0.1:8080")?;
    let pool = ThreadPool::new(4);

    for stream in listener.incoming().take(4){
        let stream_ = stream.unwrap();
        pool.execute(||{handle_client(stream_)});
    }
    Ok(())
}

lib.rs

use std::thread;
use std::sync::mpsc;
use std::sync::Arc;
use std::sync::Mutex;
use core::option::Option::Some;

struct Worker{
    id:usize,
    thread:Option<thread::JoinHandle<()>>,
}

impl Worker{
    pub fn new(id:usize, receiver:Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker{
        let thread = thread::spawn(move||{
            loop{
                let message = receiver.lock().unwrap().recv().unwrap();
                match message{
                    Message::NewJob(job) =>{
                        println!("Worker {} got a job !",id);
                        job();
                    }
                    Message::Teiminate => {
                        println!("Worker {} break !",id);
                        break;
                    }
                }
            }
        });

        Worker {
            id:id,
            thread:Some(thread)
        }
    }

}


type Job = Box<dyn FnOnce() + Send +'static>;

enum Message{
    NewJob(Job),
    Teiminate,
}

pub struct ThreadPool{
    workers:Vec<Worker>,
    sender:mpsc::Sender<Message>
}


impl ThreadPool{
    pub fn new(size:usize) ->Self{
        assert!(size>0);
        let mut workers = Vec::with_capacity(size);
        let (sender,receiver) = mpsc::channel();
        let receiver = Arc::new(Mutex::new(receiver));

        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){
        // 发送信息给终端,等待停止服务。
        for _ in &mut self.workers{
            self.sender.send(Message::Teiminate).unwrap();
        }

        for worker in &mut self.workers{
            if let Some(thread) = worker.thread.take(){
                thread.join().unwrap();
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值