Rust10 Building a Multithreaded Web Server [End]

Rust学习笔记

Rust编程语言入门教程课程笔记

参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)

Lecture 20: Final Project: Building a Multithreaded Web Server

src/main.rs

use std::fs;
use std::{io::{prelude::*, BufReader},net::{TcpListener, TcpStream},
};
use std::thread;
use std::time::Duration;
use hello::ThreadPool;fn main() {// bind to a portlet listener = TcpListener::bind("127.0.0.1:7878").unwrap(); let pool = ThreadPool::new(4);// set a limit on the number of threads in the pool// listen for incoming connectionsfor stream in listener.incoming().take(2) {// only accept two connectionslet stream = stream.unwrap();// println!("Connection established!");// handle each connection// handle_connection(stream);// spawn a new thread for each connection// thread::spawn(|| {//     handle_connection(stream);//suffer from ddos attack// });pool.execute(|| {handle_connection(stream);});}println!("Shutting down.");
}fn handle_connection(mut stream: TcpStream) {// let buf_reader = BufReader::new(&mut stream);// let http_request: Vec<_> = buf_reader//     .lines()//     .map(|result| result.unwrap())//     .take_while(|line| !line.is_empty())//     .collect();// println!("Request: {:#?}", http_request);let mut buffer = [0; 1024];stream.read(&mut buffer).unwrap();let get = b"GET / HTTP/1.1\r\n";let sleep = b"GET /sleep HTTP/1.1\r\n";//Reading a Request// Request Format// Method Request-URI HTTP-Version CRLF// headers CRLF// message-body// Example// Request: [//     "GET / HTTP/1.1",//     "Host: 127.0.0.1:7878",//     "Connection: keep-alive",//     "sec-ch-ua: \"Google Chrome\";v=\"119\", \"Chromium\";v=\"119\", \"Not?A_Brand\";v=\"24\"",//     "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/119.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",//     "Accept-Language: zh-CN,zh;q=0.9,en;q=0.8",// ]   //Writing a Response// Response Format// HTTP-Version Status-Code Reason-Phrase CRLF// headers CRLF// message-body//let response = "HTTP/1.1 200 OK\r\n\r\n";// let contents = fs::read_to_string("hello.html").unwrap();// let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", contents);// write the response to the stream// stream.write(response.as_bytes()).unwrap();// stream.flush().unwrap();// if buffer.starts_with(get) {//     let contents = fs::read_to_string("hello.html").unwrap();//     let response = format!("HTTP/1.1 200 OK\r\n\r\n{}", contents);//     stream.write(response.as_bytes()).unwrap();//     stream.flush().unwrap();// } else {//     // other request//     let status_line = "HTTP/1.1 404 NOT FOUND\r\n\r\n";//     let contents = fs::read_to_string("404.html").unwrap();//     let response = format!("{}{}", status_line, contents);//     stream.write(response.as_bytes()).unwrap();//     stream.flush().unwrap();// }// Refactoringlet (status_line, filename) = if buffer.starts_with(get) {("HTTP/1.1 200 OK\r\n\r\n", "hello.html")} else if buffer.starts_with(sleep) {// simulate a slow request// simulate a slow requeststd::thread::sleep(std::time::Duration::from_secs(5));("HTTP/1.1 200 OK\r\n\r\n", "hello.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();
}

src/lib.rs

use std::thread;
use std::sync::{mpsc, Arc, Mutex};enum Message {NewJob(Job),Terminate,
}struct Worker {id: usize,// thread: thread::JoinHandle<()>,thread: Option<thread::JoinHandle<()>>,
}impl Worker {fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Message>>>) -> Worker {// let thread = thread::spawn(|| {});// let thread = thread::spawn(|| {//     receiver;// });// let thread = thread::spawn(move || loop {//     while let Ok(_) = receiver.lock().unwrap().recv().unwrap(){//         println!("Worker {} got a job; executing.", id);//         job.call_box();//     }// });let thread = thread::spawn(move || loop {let message = receiver.lock().unwrap().recv().unwrap();match message {Message::NewJob(job) => {println!("Worker {} got a job; executing.", id);job.call_box();},Message::Terminate => {println!("Worker {} was told to terminate.", id);break;},}});Worker { id, thread: Some(thread) }}// fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {//     let thread = thread::spawn(|| {//         // loop {//         //     receiver.lock().unwrap().recv().unwrap();//         // }//         loop {//             let job = receiver.lock().unwrap().recv().unwrap();//             println!("Worker {} got a job; executing.", id);//             job.call_box();//         }//     });//     Worker { id, thread }// }
}pub struct ThreadPool {// threads: Vec<thread::JoinHandle<()>>,workers: Vec<Worker>,// sender: mpsc::Sender<Job>,sender: mpsc::Sender<Message>,
}impl ThreadPool {/// Create a new ThreadPool/// /// The size is the number of threads in the pool/// /// # Panics/// /// The `new` function will panic if the size is zero// // pub fn new(size: usize) -> ThreadPool {//     assert!(size > 0);//     let (sender, receiver) = mpsc::channel();//     let mut workers = Vec::with_capacity(size);//     for id in 0..size {//         workers.push(Worker::new(id, receiver));//     }//     ThreadPool { workers, sender }// }pub fn new(size: usize) -> ThreadPool {assert!(size > 0);let (sender, receiver) = mpsc::channel();let receiver = Arc::new(Mutex::new(receiver));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)whereF: FnOnce() + Send + 'static,{let job = Box::new(f);//Box<dyn FnOnce() + Send + 'static>// self.sender.send(job).unwrap();self.sender.send(Message::NewJob(job)).unwrap();}// the execute method should be similar with thread::spawn// pub fn spawn<F, T>(f: F) -> JoinHandle<T>// where//     F: FnOnce() -> T + Send + 'static,//     T: Send + 'static,// {//     Builder::new().spawn(f).expect("failed to spawn thread")// }}impl Drop for ThreadPool {fn drop(&mut self) {println!("Sending terminate message to all workers.");// for worker in &mut self.workers {//     println!("Shutting down worker {}", worker.id);//     worker.thread.join().unwrap();// }// for worker in &mut self.workers {//     println!("Shutting down worker {}", worker.id);//     // worker.thread.join().unwrap();//     if let Ok(_) = worker.thread.join() {//         println!("Worker {} shut down successfully.", worker.id);//     } else {//         println!("Worker {} failed to shut down.", worker.id);//     }// }for _ in &mut self.workers {self.sender.send(Message::Terminate).unwrap();}println!("Shutting down all workers.");for worker in &mut self.workers {// println!("Shutting down worker {}", worker.id);// worker.thread.join().unwrap();if let Some(thread) = worker.thread.take() {if let Ok(_) = thread.join() {println!("Worker {} shut down successfully.", worker.id);} else {println!("Worker {} failed to shut down.", worker.id);}}}}
}// struct Job;
type Job = Box<dyn FnBox + Send + 'static>;trait FnBox {fn call_box(self: Box<Self>);
}impl <F: FnOnce()> FnBox for F {fn call_box(self: Box<F>) {(*self)()}
}

hello.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>Hello World</title>
</head><body><h1>Hello World</h1><p><?phpecho "Hello World";?></p>
</body></html>

404.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><title>404</title>
</head><body><h1>Oops!</h1><p>Page not found</p>
</body></html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/170754.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

84基于matlab的数字图像处理

基于matlab的数字图像处理&#xff0c;数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 84matlab数字图像处理图像增强 (xiaohongshu.com)https://www.xiaohongshu.com/explore/656219d80000000032034dea

python小数据分析小结及算法实践集锦

在缺乏大量历史数据的新兴技术和产业中&#xff0c;商业分析可能会面临一些挑战。然而&#xff0c;有一些技术和方法可以帮助分析者在数据不充分的情况下进行科学化商业分析&#xff0c;并为决策提供支持。 1. 当面对缺乏大量历史数据的新兴技术和产业时所采常用的技术和方法 …

二进制数据转换成十六进制表示 binascii.hexlify()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 二进制数据转换成十六进制表示 binascii.hexlify() 选择题 binascii.hexlify()参数的数据类型可以是&#xff1f; import binascii number 11 byte_data number.to_bytes() hex_data bin…

Android : Java中创建线程的几种方式_简单应用

主方法 MainTest.java package com.example.mythread;import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask;public class MainTest {public static void main(String[] data){ // 以下的方…

C#面试问题整理

sqlserver中视图和表的区别 在 SQL Server 中&#xff0c;视图&#xff08;View&#xff09;和表&#xff08;Table&#xff09;是不同的对象&#xff0c;它们有以下几点区别&#xff1a; 数据存储方式&#xff1a;表是一种实际存储数据的数据库对象&#xff0c;它包含列和行&…

Day45:300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

文章目录 300.最长递增子序列思路代码实现 674. 最长连续递增序列思路代码实现 718. 最长重复子数组思路代码实现 300.最长递增子序列 题目链接 思路 单个字符都是一个长为1的子序列&#xff0c;直接初始化dp为1。先固定一个元素位置i&#xff0c;判断0-i范围内到i的最长子序…

数字图像处理-Matlab实验

实验一 图像增强 实验内容: 对于给定的低对比度测试图像,利用灰度图像直方图均衡化算法进行图像视觉效果增强。 对于给定的低照度彩色测试图像,结合颜色空间转换和灰度图像直方图均衡化算法进行图像视觉效果增强。 实验数据: Test1_1.jpg: Test1_2.jpg: 实验步骤: %% …

谈谈Redis持久化

目录 前言 RDB AOF 总结 前言 我们都知道Redis 是基于内存的数据库&#xff0c;一旦服务器的进程退出&#xff0c;数据库数据就会随之丢失&#xff0c;这不是我们想看到的&#xff0c;为了避免这个问题&#xff0c;Redis 为我们提供了俩种持久化方案&#xff0c;将数据保存…

Linux加强篇006-存储结构与管理硬盘

目录 前言 1. 从“/”开始 2. 物理设备命名规则 3. 文件系统与数据资料 4. 挂载硬件设备 5. 添加硬盘设备 6. 添加交换分区 7. 磁盘容量配额 8. VDO虚拟数据优化 9. 软硬方式链接 前言 悟已往之不谏&#xff0c;知来者之可追。实迷途其未远&#xff0c;觉今是而昨非…

C#,《小白学程序》第二十四课:大数的阶乘(BigInteger Factorial)算法与源程序

1 文本格式 /// <summary> /// 《小白学程序》第二十四课&#xff1a;大数&#xff08;BigInteger&#xff09;的阶乘 /// 用于大数的阶乘算法&#xff08;原始算法&#xff09; /// </summary> /// <param name"a"></param> /// <retur…

【LeetCode】121. 买卖股票的最佳时机

121. 买卖股票的最佳时机 难度&#xff1a;简单 题目 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获…

做直播服务器要什么样的配置呢?

现在直播行业越来越火爆&#xff0c;大大小小的平台或者企业都选择通过直播卖货的方式出售产品&#xff0c;直播的内容还有观看直播的人数等等都影响了服务器的配置需求&#xff0c;今天小编就给大家讲一讲吧&#xff01; 1、内存&#xff1a;直播服务器需要足够的内存才能支持…

Kafka常见面试问题

1、Kafka分区设计及主副本如何同步 Apache Kafka是一种分布式流处理平台&#xff0c;它使用分布式复制协议来实现高可用性和容错性。在Kafka中&#xff0c;每个主题&#xff08;topic&#xff09;都有一个或多个分区&#xff08;partition&#xff09;&#xff0c;每个分区都有…

黑马点评-Feed流的实现方案,基于推拉结合模式实现笔记推送

Feed流实现方案 我们关注了博主之后,当用户发布了动态后我们应该把这些数据推送给粉丝,关注推送也叫作Feed(投喂)流,通过无限下拉刷新获取新的信息 传统的模式内容检索: 粉丝需要主动通过搜索引擎或者是其他方式去查找想看的内容新型Feed流的效果: 系统分析用户到底想看什么,…

高效的绩效面谈有哪些特点?

目前许多企业有相应的考核制度&#xff0c;绩效管理投入力度也较大&#xff0c;然而仅仅开展考核&#xff0c;很难促进绩效的质变提高&#xff0c;要如何去总结过去的不足、如何针对个体的特点制定下一步的工作计划&#xff1f;绩效面谈是解决以上问题的良策。 若不进行及时且…

【UGUI】中Content Size Fitter)组件-使 UI 元素适应其内容的大小

官方文档&#xff1a;使 UI 元素适应其内容的大小 - Unity 手册 必备组件&#xff1a;Content Size Fitter 通常&#xff0c;在使用矩形变换定位 UI 元素时&#xff0c;应手动指定其位置和大小&#xff08;可选择性地包括使用父矩形变换进行拉伸的行为&#xff09;。 但是&a…

突破技术障碍:软件工程师如何应对项目中的难题?

在软件开发项目中&#xff0c;工程师常常会遇到各种技术难题。这些难题可能涉及到复杂的算法、不兼容的系统、难以预见的软件行为&#xff0c;或者其他许多方面。 以下是一些策略和方法&#xff0c;可以帮助软件工程师有效地应对这些挑战&#xff1a; 1、理解问题&#xff1a;…

第十六章 处理空字符串和 Null 值

文章目录 第十六章 处理空字符串和 Null 值空字符串和 Null 值的默认映射导出值控制空元素的形式 第十六章 处理空字符串和 Null 值 类和属性参数 XMLUSEEMPTYELEMENT XMLIGNORENULL XMLNILNOOBJECT XMLNIL 空字符串和 Null 值的默认映射 下表总结了空字符串和 null 值的…

count=0语句的位置

简洁一点的代码&#xff1a; 像count0这种语句要注意放好位置&#xff0c;尤其是在循环里。

SAP Smartform小结

SAP系统做打印单据用的, 感觉很不好用, 特别是要嵌入韩文时必须使用嵌入的word编辑器,运行速度简直不可忍受. 见过一些Adobe interactive form的示例, 看着相当不错, 不过据说需要花money额外买licence, 哪有smartform这种免费东西来得实惠. 一般打印需求,会要求有标题抬头,打…