add web server chapter in multi thread section

pull/1163/head
sunface 2 years ago
parent 60e26cec08
commit e36b33ec71

@ -5,7 +5,7 @@ title = "Rust语言圣经(Rust Course)"
src = "src" src = "src"
[output.html] [output.html]
additional-css = ["theme/style3.css"] additional-css = ["theme/style.css"]
additional-js = ["assets/custom.js", "assets/bigPicture.js"] additional-js = ["assets/custom.js", "assets/bigPicture.js"]
git-repository-url = "https://github.com/sunface/rust-course" git-repository-url = "https://github.com/sunface/rust-course"
edit-url-template = "https://github.com/sunface/rust-course/edit/main/{path}" edit-url-template = "https://github.com/sunface/rust-course/edit/main/{path}"

@ -12,7 +12,10 @@
<!-- [Rust 语言周刊](rust-weekly.md) --> <!-- [Rust 语言周刊](rust-weekly.md) -->
<!-- [Rust 翻译计划( 代号 Rustt )](rustt.md) --> <!-- [Rust 翻译计划( 代号 Rustt )](rustt.md) -->
# 快速开始
# Rust 语言基础学习
--- ---
@ -24,10 +27,6 @@
- [下载依赖太慢了?](first-try/slowly-downloading.md) - [下载依赖太慢了?](first-try/slowly-downloading.md)
# Rust 语言学习
---
- [Rust 基础入门](basic/intro.md) - [Rust 基础入门](basic/intro.md)
- [变量绑定与解构](basic/variable.md) - [变量绑定与解构](basic/variable.md)
@ -78,6 +77,11 @@
- [使用环境变量](basic-practice/envs.md) - [使用环境变量](basic-practice/envs.md)
- [重定向错误信息的输出](basic-practice/stderr.md) - [重定向错误信息的输出](basic-practice/stderr.md)
- [使用迭代器来改进程序(可选)](basic-practice/iterators.md) - [使用迭代器来改进程序(可选)](basic-practice/iterators.md)
# Rust 语言进阶学习
---
- [Rust 高级进阶](advance/intro.md) - [Rust 高级进阶](advance/intro.md)
- [生命周期](advance/lifetime/intro.md) - [生命周期](advance/lifetime/intro.md)
- [深入生命周期](advance/lifetime/advance.md) - [深入生命周期](advance/lifetime/advance.md)
@ -106,7 +110,6 @@
- [线程同步锁、Condvar 和信号量](advance/concurrency-with-threads/sync1.md) - [线程同步锁、Condvar 和信号量](advance/concurrency-with-threads/sync1.md)
- [线程同步Atomic 原子操作与内存顺序](advance/concurrency-with-threads/sync2.md) - [线程同步Atomic 原子操作与内存顺序](advance/concurrency-with-threads/sync2.md)
- [基于 Send 和 Sync 的线程安全](advance/concurrency-with-threads/send-sync.md) - [基于 Send 和 Sync 的线程安全](advance/concurrency-with-threads/send-sync.md)
- [实践应用:多线程 Web 服务器](advance/concurrency-with-threads/web-server.md)
- [全局变量](advance/global-variable.md) - [全局变量](advance/global-variable.md)
- [错误处理](advance/errors.md) - [错误处理](advance/errors.md)
- [Unsafe Rust](advance/unsafe/intro.md) - [Unsafe Rust](advance/unsafe/intro.md)
@ -124,7 +127,10 @@
- [一些疑难问题的解决办法](advance/async/pain-points-and-workarounds.md) - [一些疑难问题的解决办法](advance/async/pain-points-and-workarounds.md)
- [实践应用Async Web 服务器](advance/async/web-server.md) - [实践应用Async Web 服务器](advance/async/web-server.md)
- [进阶实战: 实现一个简单 Redis](advance-practice/intro.md) - [进阶实战1: 实现一个 web 服务器](advance-practice1/intro.md)
- [构建单线程 Web 服务器](advance-practice1/web-server.md)
- [进阶实战2: 实现一个简单 Redis](advance-practice/intro.md)
- [tokio 概览](advance-practice/overview.md) - [tokio 概览](advance-practice/overview.md)
- [使用初印象](advance-practice/getting-startted.md) - [使用初印象](advance-practice/getting-startted.md)
- [创建异步任务](advance-practice/spawning.md) - [创建异步任务](advance-practice/spawning.md)
@ -239,7 +245,7 @@
- [双单向链表](too-many-lists/advanced-lists/double-singly.md) - [双单向链表](too-many-lists/advanced-lists/double-singly.md)
- [栈上的链表](too-many-lists/advanced-lists/stack-allocated.md) - [栈上的链表](too-many-lists/advanced-lists/stack-allocated.md)
# 高级专题 # 攻克编译错误
--- ---
@ -269,6 +275,10 @@
- [线程间传递消息导致主线程无法结束](compiler/pitfalls/main-with-channel-blocked.md) - [线程间传递消息导致主线程无法结束](compiler/pitfalls/main-with-channel-blocked.md)
- [警惕 UTF-8 引发的性能隐患](compiler/pitfalls/utf8-performance.md) - [警惕 UTF-8 引发的性能隐患](compiler/pitfalls/utf8-performance.md)
# 性能优化
---
- [Rust 性能优化 todo](profiling/intro.md) - [Rust 性能优化 todo](profiling/intro.md)
- [深入内存 todo](profiling/memory/intro.md) - [深入内存 todo](profiling/memory/intro.md)
@ -296,12 +306,14 @@
- [编译器优化 todo](profiling/compiler/optimization/intro.md) - [编译器优化 todo](profiling/compiler/optimization/intro.md)
- [Option 枚举 todo](profiling/compiler/optimization/option.md) - [Option 枚举 todo](profiling/compiler/optimization/option.md)
- [标准库解析 todo](std/intro.md)
<!-- - [标准库解析 todo](std/intro.md)
- [标准库使用最佳实践 todo](std/search.md) - [标准库使用最佳实践 todo](std/search.md)
- [Vector 常用方法 todo](std/vector.md) - [Vector 常用方法 todo](std/vector.md)
- [HashMap todo](std/hashmap.md) - [HashMap todo](std/hashmap.md)
- [Iterator 常用方法 todo](std/iterator.md) - [Iterator 常用方法 todo](std/iterator.md) -->
<!-- - [配置文件解析 todo](cookbook/config.md) <!-- - [配置文件解析 todo](cookbook/config.md)
- [编解码 todo](cookbook/encoding/intro.md) - [编解码 todo](cookbook/encoding/intro.md)

@ -0,0 +1,13 @@
# 实践应用多线程Web服务器
一般来说,现代化的 web 服务器往往都基于更加轻量级的协程或 async/await 等模式实现,但是基于本章的内容,我们还是采取较为传统的多线程的方式来实现,即:一个请求连接分配一个线程去独立处理,当然还有升级版的线程池。
在本章中你将了解:
1. 学习一点 TCP 和 HTTP
2. 在套接字 socket 上监听进入的 TCP 连接
3. 解析 HTTP 请求
4. 创建合适的 HTTP 应答
5. 使用线程池来提升 web 服务器的吞吐量
> 本章的实现方法并不是在 Rust 中实现 Web 服务器的最佳方法,后续章节的 async/await 会更加适合!

@ -1,18 +1,4 @@
# 实践应用多线程Web服务器 # 构建单线程 Web 服务器
一般来说,现代化的 web 服务器往往都基于更加轻量级的协程或 async/await 等模式实现,但是基于本章的内容,我们还是采取较为传统的多线程的方式来实现,即:一个请求连接分配一个线程去独立处理,当然还有升级版的线程池。
在本章中你将了解:
1. 学习一点 TCP 和 HTTP
2. 在套接字 socket 上监听进入的 TCP 连接
3. 解析 HTTP 请求
4. 创建合适的 HTTP 应答
5. 使用线程池来提升 web 服务器的吞吐量
> 本章的实现方法并不是在 Rust 中实现 Web 服务器的最佳方法,后续章节的 async/await 会更加适合!
## 构建单线程 Web 服务器
在开始之前先来简单回顾下构建所需的网络协议: HTTP 和 TCP。这两种协议都是请求-应答模式的网络协议,意味着在客户端发起请求后,服务器会监听并处理进入的请求,最后给予应答,至于这个过程怎么进行,取决于具体的协议定义。 在开始之前先来简单回顾下构建所需的网络协议: HTTP 和 TCP。这两种协议都是请求-应答模式的网络协议,意味着在客户端发起请求后,服务器会监听并处理进入的请求,最后给予应答,至于这个过程怎么进行,取决于具体的协议定义。
@ -22,7 +8,7 @@
更加深入的学习网络协议并不属于本书的范畴,因此让我们从如何读取 TCP 传输的字节流开始吧。 更加深入的学习网络协议并不属于本书的范畴,因此让我们从如何读取 TCP 传输的字节流开始吧。
### 监听 TCP 连接 ## 监听 TCP 连接
先来创建一个全新的项目: 先来创建一个全新的项目:
@ -75,7 +61,7 @@ Connection established!
由于 `listener.incoming` 会在当前阻塞式监听,也就是 `main` 线程会被阻塞,我们最后需要通过 `ctrl + c` 来结束程序进程。 由于 `listener.incoming` 会在当前阻塞式监听,也就是 `main` 线程会被阻塞,我们最后需要通过 `ctrl + c` 来结束程序进程。
### 读取请求 ## 读取请求
连接建立后,就可以开始读取客户端传来的数据: 连接建立后,就可以开始读取客户端传来的数据:
@ -143,7 +129,7 @@ Request: [
呦,还挺长的,是不是长得很像我们以前见过的 HTTP 请求 JSON来简单分析下。 呦,还挺长的,是不是长得很像我们以前见过的 HTTP 请求 JSON来简单分析下。
### HTTP 请求长啥样 ## HTTP 请求长啥样
刚才的文本挺长的,但其实符合以下的格式: 刚才的文本挺长的,但其实符合以下的格式:
@ -159,7 +145,7 @@ message-body
大家可以尝试换一个浏览器再访问一次,看看不同的浏览器请求携带的 headers 是否不同。 大家可以尝试换一个浏览器再访问一次,看看不同的浏览器请求携带的 headers 是否不同。
### 请求应答 ## 请求应答
目前为止都是在服务器端的操作浏览器的请求依然还会报错是时候给予相应的请求应答了HTTP 格式类似: 目前为止都是在服务器端的操作浏览器的请求依然还会报错是时候给予相应的请求应答了HTTP 格式类似:
@ -198,7 +184,7 @@ fn handle_connection(mut stream: TcpStream) {
重新启动服务器,然后再观察下浏览器中的输出,这次应该不再有报错,而是一个空白页面,因为没有返回任何具体的数据( message-body ),上面只是一条最简单的符合 HTTP 格式的数据。 重新启动服务器,然后再观察下浏览器中的输出,这次应该不再有报错,而是一个空白页面,因为没有返回任何具体的数据( message-body ),上面只是一条最简单的符合 HTTP 格式的数据。
### 返回 HTML 页面 ## 返回 HTML 页面
空白页面显然会让人不知所措,那就返回一个简单的 HTML 页面,给用户打给招呼。 空白页面显然会让人不知所措,那就返回一个简单的 HTML 页面,给用户打给招呼。
@ -254,7 +240,7 @@ fn handle_connection(mut stream: TcpStream) {
> 用这么奇怪的格式返回应答数据,原因只有一个,我们在模拟实现真正的 http web 服务器框架。事实上,写逻辑代码时,只需使用现成的 web 框架( 例如 [`rocket`](https://rocket.rs) )去启动 web 服务即可,解析请求数据和返回应答数据都已经被封装在 API 中,非常简单易用 > 用这么奇怪的格式返回应答数据,原因只有一个,我们在模拟实现真正的 http web 服务器框架。事实上,写逻辑代码时,只需使用现成的 web 框架( 例如 [`rocket`](https://rocket.rs) )去启动 web 服务即可,解析请求数据和返回应答数据都已经被封装在 API 中,非常简单易用
### 验证请求和选择性应答 ## 验证请求和选择性应答
用户想要获取他的个人信息,你给他 say hi用户想要查看他的某篇文章内容你给他 say hi, 好吧用户想要骂你,你还是给它 say hi。 用户想要获取他的个人信息,你给他 say hi用户想要查看他的某篇文章内容你给他 say hi, 好吧用户想要骂你,你还是给它 say hi。
@ -346,4 +332,3 @@ fn handle_connection(mut stream: TcpStream) {
至此,单线程版本的服务器已经完成,但是说实话,没啥用,总不能让你的用户排队等待访问吧,那也太糟糕了... 至此,单线程版本的服务器已经完成,但是说实话,没啥用,总不能让你的用户排队等待访问吧,那也太糟糕了...
## 多线程 web 服务器

@ -57,7 +57,7 @@
.chapter li.chapter-item { .chapter li.chapter-item {
/* 没有文件时的文字颜色 */ /* 没有文件时的文字颜色 */
color: #939da3; color: #939da3;
margin-top: 1rem; margin-top: 1.5rem;
} }
/* 修改滚动条宽度 */ /* 修改滚动条宽度 */
Loading…
Cancel
Save