diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index fbf4553..999df14 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -111,10 +111,10 @@
- [高级类型](ch19-04-advanced-types.md)
- [高级函数与闭包](ch19-05-advanced-functions-and-closures.md)
-- [Final Project: Building a Multithreaded Web Server](ch20-00-final-project-a-web-server.md)
- - [A Single Threaded Web Server](ch20-01-single-threaded.md)
- - [How Slow Requests Affect Throughput](ch20-02-slow-requests.md)
- - [Designing the Thread Pool Interface](ch20-03-designing-the-interface.md)
- - [Creating the Thread Pool and Storing Threads](ch20-04-storing-threads.md)
- - [Sending Requests to Threads Via Channels](ch20-05-sending-requests-via-channels.md)
- - [Graceful Shutdown and Cleanup](ch20-06-graceful-shutdown-and-cleanup.md)
\ No newline at end of file
+- [最后的项目: 构建多线程 web server](ch20-00-final-project-a-web-server.md)
+ - [单线程 web server](ch20-01-single-threaded.md)
+ - [慢请求如何影响吞吐率](ch20-02-slow-requests.md)
+ - [设计线程池接口](ch20-03-designing-the-interface.md)
+ - [创建线程池并储存线程](ch20-04-storing-threads.md)
+ - [使用通道向线程发送请求](ch20-05-sending-requests-via-channels.md)
+ - [Graceful Shutdown 与清理](ch20-06-graceful-shutdown-and-cleanup.md)
\ No newline at end of file
diff --git a/src/ch19-05-advanced-functions-and-closures.md b/src/ch19-05-advanced-functions-and-closures.md
index ddfe70f..37374ae 100644
--- a/src/ch19-05-advanced-functions-and-closures.md
+++ b/src/ch19-05-advanced-functions-and-closures.md
@@ -30,4 +30,76 @@ fn main() {
列表 19-34:使用 `fn` 类型接受函数指针作为参数
-这会打印出 `The answer is: 12`。
\ No newline at end of file
+这会打印出 `The answer is: 12`。`do_twice` 中的 `f` 被指定为一个接受一个 `i32` 参数并返回 `i32` 的 `fn`。接着就可以在 `do_twice` 函数体中调用 `f`。在 `main` 中,可以将函数名 `add_one` 作为第一个参数传递给 `do_twice`。
+
+不同于闭包,`fn` 是一个类型而不是一个 trait,所以直接指定 `fn` 作为参数而不是声明一个带有 `Fn` 作为 trait bound 的泛型参数。
+
+函数指针实现了所有三个闭包 trait(`Fn`、`FnMut` 和 `FnOnce`),所以总是可以在调用期望闭包的函数时传递函数指针作为参数。倾向于编写使用泛型和闭包 trait 的函数,这样它就能接受函数或闭包作为参数。一个只期望接受 `fn` 的情况的例子是与不存在闭包的外部代码交互时:C 语言的函数可以接受函数作为参数,但没有闭包。
+
+比如,如果希望使用 `map` 函数将一个数字 vector 转换为一个字符串 vector,就可以使用闭包:
+
+```rust
+let list_of_numbers = vec![1, 2, 3];
+let list_of_strings: Vec = list_of_numbers
+ .iter()
+ .map(|i| i.to_string())
+ .collect();
+```
+
+或者可以将函数作为 `map` 的参数来代替闭包:
+
+```rust
+let list_of_numbers = vec![1, 2, 3];
+let list_of_strings: Vec = list_of_numbers
+ .iter()
+ .map(ToString::to_string)
+ .collect();
+```
+
+注意这里必须使用“高级 trait”部分讲到的完全限定语法,因为存在多个叫做 `to_string` 的函数;这里使用定义于 `ToString` trait 的 `to_string` 函数,标准库为所有实现了 `Display` 的类型实现了这个 trait。
+
+一些人倾向于函数风格,一些人喜欢闭包。他们最终都会产生同样的代码,所以请使用你更明白的吧。
+
+### 返回闭包
+
+因为闭包以 trait 的形式体现,返回闭包就有点微妙了;不能直接这么做。对于大部分需要返回 trait 的情况,可以使用是实现了期望返回的 trait 的具体类型替代函数的返回值。但是这不能用于闭包。他们没有一个可返回的具体类型;例如不允许使用函数指针 `fn` 作为返回值类型。
+
+这段代码尝试直接返回闭包,它并不能编译:
+
+```rust
+fn returns_closure() -> Fn(i32) -> i32 {
+ |x| x + 1
+}
+```
+
+编译器给出的错误是:
+
+```
+error[E0277]: the trait bound `std::ops::Fn(i32) -> i32 + 'static:
+std::marker::Sized` is not satisfied
+ --> :2:25
+ |
+2 | fn returns_closure() -> Fn(i32) -> i32 {
+ | ^^^^^^^^^^^^^^ the trait `std::marker::Sized` is
+ not implemented for `std::ops::Fn(i32) -> i32 + 'static`
+ |
+ = note: `std::ops::Fn(i32) -> i32 + 'static` does not have a constant size
+ known at compile-time
+ = note: the return type of a function must have a statically known size
+```
+
+又是 `Sized` trait!Rust 并不知道需要多少空间来储存闭包。不过我们在上一部分见过这种情况的解决办法:可以使用 trait 对象:
+
+```rust
+fn returns_closure() -> Box i32> {
+ Box::new(|x| x + 1)
+}
+```
+
+关于 trait 对象的更多内容,请参考第十八章。
+
+## 总结
+
+好的!现在我们学习了 Rust 并不常用但你可能用得着的功能。我们介绍了很多复杂的主题,这样当你在错误信息提示或阅读他人代码时遇到他们时,至少可以说已经见过这些概念和语法了。
+
+现在,让我们再开始一个项目,将本书所学的所有内容付与实践!
\ No newline at end of file
diff --git a/src/ch20-00-final-project-a-web-server.md b/src/ch20-00-final-project-a-web-server.md
new file mode 100644
index 0000000..ec93403
--- /dev/null
+++ b/src/ch20-00-final-project-a-web-server.md
@@ -0,0 +1,23 @@
+# 最后的项目: 构建多线程 web server
+
+> [ch20-00-final-project-a-web-server.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch20-00-final-project-a-web-server.md)
+>
+> commit 08e50d5e147ad290d88efd5c58365000723626df
+
+这是一次漫长的旅途,不过我们做到了!这一章便是本书的结束。离别是如此甜蜜的悲伤。不过在我们结束之前,再来一起构建另一个项目,来展示最后几章所学,同时复习更早的章节。
+
+下面就是我们将要做的:一个简单的 web server:
+
+![hello from rust](img/hello.png)
+
+为此我们将:
+
+1. 学习一些 TCP 与 HTTP 知识
+2. 在套接字(socket)上监听 TCP 请求
+3. 解析少量的 HTTP 请求
+4. 创建一个合适的 HTTP 响应
+5. 通过线程池改善 server 的吞吐量
+
+在开始之前,需要提到一点:如果你曾在生产环境中编写过这样的代码,还有很多更好的做法。特别需要指出的是,crates.io 上提供了很多更完整健壮的 web server 和 线程池实现,要不我们编写的好很多。
+
+然而,本章的目的在于学习,而不是走捷径。因为 Rust 是一个系统编程语言,能够选择处理什么层次的抽象。我们能够选择比其他语言可能或可用的层次更低的层次。所以我们将自己编写一个基础的 HTTP server 和线程池,以便学习将来可能用到的 crate 背后的通用理念和技术。
\ No newline at end of file
diff --git a/src/ch20-01-single-threaded.md b/src/ch20-01-single-threaded.md
new file mode 100644
index 0000000..a845d91
--- /dev/null
+++ b/src/ch20-01-single-threaded.md
@@ -0,0 +1,10 @@
+## 单线程 web server
+
+> [ch20-01-single-threaded.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch20-01-single-threaded.md)
+>
+> commit 2e269ff82193fd65df8a87c06561d74b51ac02f7
+
+首先让我们创建一个可运行的单线程 web server。我们将处理 TCP 和 HTTP 请求和响应的原始字节来从 server 向浏览器发送 HTML。首先先快速了解一下涉及到的协议。
+
+**超文本传输协议**(*Hypertext Transfer Protocol*,*HTTP*)驱动着现在的互联网,它构建于**传输控制协议**(*Transmission Control Protocol*,*TCP*)的基础上。这里并不会过多的涉及细节,只做简单的概括:TCP 是一个底层协议,HTTP 是 TCP 之上的高级协议。这两个都是一种被称为**请求-响应协议**(*request-response protocol*)的协议,也就是说,有**客户端**(*client*)来初始化请求,并有**服务端**(*server*)监听请求并向客户端提供响应。请求与响应的内容由协议本身定义。
+
diff --git a/src/img/hello.png b/src/img/hello.png
new file mode 100644
index 0000000..19e2cbc
Binary files /dev/null and b/src/img/hello.png differ