Skip to content

Commit bfa823d

Browse files
committed
More backporting
1 parent 8ee4af9 commit bfa823d

File tree

6 files changed

+136
-113
lines changed

6 files changed

+136
-113
lines changed

nostarch/chapter21.md

Lines changed: 67 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ Figure 21-1: Our final shared project
3131
Before we get started, we should mention two details. First, the method we’ll
3232
use won’t be the best way to build a web server with Rust. Community members
3333
have published a number of production-ready crates available at
34-
https://crates.io that provide more complete web server and thread pool
35-
implementations than we’ll build. However, our intention in this chapter is to
36-
help you learn, not to take the easy route. Because Rust is a systems
34+
crates.io at *https://crates.io/* that provide more complete web server and thread
35+
pool implementations than we’ll build. However, our intention in this chapter is
36+
to help you learn, not to take the easy route. Because Rust is a systems
3737
programming language, we can choose the level of abstraction we want to work
3838
with and can go to a lower level than is possible or practical in other
3939
languages.
@@ -166,8 +166,17 @@ It could also be that the browser is trying to connect to the server multiple
166166
times because the server isn’t responding with any data. When `stream` goes out
167167
of scope and is dropped at the end of the loop, the connection is closed as
168168
part of the `drop` implementation. Browsers sometimes deal with closed
169-
connections by retrying, because the problem might be temporary. The important
170-
factor is that we’ve successfully gotten a handle to a TCP connection!
169+
connections by retrying, because the problem might be temporary.
170+
171+
Browsers also sometimes open multiple connections to the server without sending
172+
any requests, so that if they *do* later send requests, those requests can
173+
happen faster. When this happens, our server will see each connection,
174+
regardless of whether there are any requests over that connection. Many
175+
versions of Chrome-based browsers do this, for example; you can disable that
176+
optimization by using private browsing mode or using a different browser.
177+
178+
The important factor is that we’ve successfully gotten a handle to a TCP
179+
connection!
171180

172181
Remember to stop the program by pressing <kbd>ctrl</kbd>-<kbd>C</kbd> when
173182
you’re done running a particular version of the code. Then restart the program
@@ -222,8 +231,8 @@ connection, we now call the new `handle_connection` function and pass the
222231
`stream` to it.
223232

224233
In the `handle_connection` function, we create a new `BufReader` instance that
225-
wraps a reference to the `stream`. `BufReader` adds buffering by managing calls
226-
to the `std::io::Read` trait methods for us.
234+
wraps a reference to the `stream`. The `BufReader` adds buffering by managing
235+
calls to the `std::io::Read` trait methods for us.
227236

228237
We create a variable named `http_request` to collect the lines of the request
229238
the browser sends to our server. We indicate that we want to collect these
@@ -643,6 +652,7 @@ finished, even if the new requests can be processed quickly. We’ll need to fix
643652
this, but first we’ll look at the problem in action.
644653

645654
<!-- Old headings. Do not remove or links may break. -->
655+
646656
<a id="simulating-a-slow-request-in-the-current-server-implementation"></a>
647657

648658
### Simulating a Slow Request
@@ -696,10 +706,10 @@ You can see how primitive our server is: real libraries would handle the
696706
recognition of multiple requests in a much less verbose way!
697707

698708
Start the server using `cargo run`. Then open two browser windows: one for
699-
*http://127.0.0.1:7878* and the other for *http://127.0.0.1:7878/sleep*. If you
700-
enter the */* URI a few times, as before, you’ll see it respond quickly. But if
701-
you enter */sleep* and then load */*, you’ll see that */* waits until `sleep`
702-
has slept for its full five seconds before loading.
709+
*http://127.0.0.1:7878* and the other for *http://127.0.0.1:7878/sleep*. If
710+
you enter the */* URI a few times, as before, you’ll see it respond quickly.
711+
But if you enter */sleep* and then load */*, you’ll see that */* waits until
712+
`sleep` has slept for its full five seconds before loading.
703713

704714
There are multiple techniques we could use to avoid requests backing up behind
705715
a slow request, including using async as we did Chapter 17; the one we’ll
@@ -1143,6 +1153,7 @@ which resizes itself as elements are inserted.
11431153
When you run `cargo check` again, it should succeed.
11441154

11451155
<!-- Old headings. Do not remove or links may break. -->
1156+
11461157
<a id ="a-worker-struct-responsible-for-sending-code-from-the-threadpool-to-a-thread"></a>
11471158

11481159
#### Sending Code from the ThreadPool to a Thread
@@ -1516,12 +1527,14 @@ src/lib.rs
15161527
15171528
impl Worker {
15181529
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
1519-
let thread = thread::spawn(move || loop {
1520-
let job = receiver.lock().unwrap().recv().unwrap();
1530+
let thread = thread::spawn(move || {
1531+
loop {
1532+
let job = receiver.lock().unwrap().recv().unwrap();
15211533
1522-
println!("Worker {id} got a job; executing.");
1534+
println!("Worker {id} got a job; executing.");
15231535
1524-
job();
1536+
job();
1537+
}
15251538
});
15261539
15271540
Worker { id, thread }
@@ -1650,7 +1663,7 @@ longer than intended if we aren’t mindful of the lifetime of the
16501663
`MutexGuard<T>`.
16511664

16521665
The code in Listing 21-20 that uses `let job = receiver.lock().unwrap().recv().unwrap();` works because with `let`, any
1653-
temporary values used in the expression on the right-hand side of the equal
1666+
temporary values used in the expression on the right hand side of the equal
16541667
sign are immediately dropped when the `let` statement ends. However, `while let` (and `if let` and `match`) does not drop temporary values until the end of
16551668
the associated block. In Listing 21-21, the lock remains held for the duration
16561669
of the call to `job()`, meaning other `Worker` instances cannot receive jobs.
@@ -1712,18 +1725,15 @@ Here is the error we get when we compile this code:
17121725
$ cargo check
17131726
Checking hello v0.1.0 (file:///projects/hello)
17141727
error[E0507]: cannot move out of `worker.thread` which is behind a mutable reference
1715-
--> src/lib.rs:52:13
1716-
|
1717-
52 | worker.thread.join().unwrap();
1718-
| ^^^^^^^^^^^^^ ------ `worker.thread` moved due to this method call
1719-
| |
1720-
| move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait
1721-
|
1728+
--> src/lib.rs:52:13
1729+
|
1730+
52 | worker.thread.join().unwrap();
1731+
| ^^^^^^^^^^^^^ ------ `worker.thread` moved due to this method call
1732+
| |
1733+
| move occurs because `worker.thread` has type `JoinHandle<()>`, which does not implement the `Copy` trait
1734+
|
17221735
note: `JoinHandle::<T>::join` takes ownership of the receiver `self`, which moves `worker.thread`
1723-
--> file:///home/.rustup/toolchains/1.82/lib/rustlib/src/rust/library/std/src/thread/mod.rs:1763:17
1724-
|
1725-
1763 | pub fn join(self) -> Result<T> {
1726-
| ^^^^
1736+
--> /rustc/4eb161250e340c8f48f66e2b929ef4a5bed7c181/library/std/src/thread/mod.rs:1876:17
17271737
17281738
For more information about this error, try `rustc --explain E0507`.
17291739
error: could not compile `hello` (lib) due to 1 previous error
@@ -1849,18 +1859,20 @@ src/lib.rs
18491859
```
18501860
impl Worker {
18511861
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
1852-
let thread = thread::spawn(move || loop {
1853-
let message = receiver.lock().unwrap().recv();
1854-
1855-
match message {
1856-
Ok(job) => {
1857-
println!("Worker {id} got a job; executing.");
1858-
1859-
job();
1860-
}
1861-
Err(_) => {
1862-
println!("Worker {id} disconnected; shutting down.");
1863-
break;
1862+
let thread = thread::spawn(move || {
1863+
loop {
1864+
let message = receiver.lock().unwrap().recv();
1865+
1866+
match message {
1867+
Ok(job) => {
1868+
println!("Worker {id} got a job; executing.");
1869+
1870+
job();
1871+
}
1872+
Err(_) => {
1873+
println!("Worker {id} disconnected; shutting down.");
1874+
break;
1875+
}
18641876
}
18651877
}
18661878
});
@@ -1965,7 +1977,7 @@ src/main.rs
19651977
use hello::ThreadPool;
19661978
use std::{
19671979
fs,
1968-
io::{prelude::*, BufReader},
1980+
io::{BufReader, prelude::*},
19691981
net::{TcpListener, TcpStream},
19701982
thread,
19711983
time::Duration,
@@ -2015,7 +2027,7 @@ src/lib.rs
20152027

20162028
```
20172029
use std::{
2018-
sync::{mpsc, Arc, Mutex},
2030+
sync::{Arc, Mutex, mpsc},
20192031
thread,
20202032
};
20212033
@@ -2084,18 +2096,20 @@ struct Worker {
20842096
20852097
impl Worker {
20862098
fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Worker {
2087-
let thread = thread::spawn(move || loop {
2088-
let message = receiver.lock().unwrap().recv();
2089-
2090-
match message {
2091-
Ok(job) => {
2092-
println!("Worker {id} got a job; executing.");
2093-
2094-
job();
2095-
}
2096-
Err(_) => {
2097-
println!("Worker {id} disconnected; shutting down.");
2098-
break;
2099+
let thread = thread::spawn(move || {
2100+
loop {
2101+
let message = receiver.lock().unwrap().recv();
2102+
2103+
match message {
2104+
Ok(job) => {
2105+
println!("Worker {id} got a job; executing.");
2106+
2107+
job();
2108+
}
2109+
Err(_) => {
2110+
println!("Worker {id} disconnected; shutting down.");
2111+
break;
2112+
}
20992113
}
21002114
}
21012115
});

nostarch/docx/chapter21.docx

-2.38 KB
Binary file not shown.

src/ch21-00-final-project-a-web-server.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ lessons.
88
For our final project, we’ll make a web server that says “hello” and looks like
99
Figure 21-1 in a web browser.
1010

11-
![hello from rust](img/trpl21-01.png)
12-
13-
<span class="caption">Figure 21-1: Our final shared project</span>
14-
1511
Here is our plan for building the web server:
1612

1713
1. Learn a bit about TCP and HTTP.
@@ -20,9 +16,13 @@ Here is our plan for building the web server:
2016
4. Create a proper HTTP response.
2117
5. Improve the throughput of our server with a thread pool.
2218

19+
![hello from rust](img/trpl21-01.png)
20+
21+
<span class="caption">Figure 21-1: Our final shared project</span>
22+
2323
Before we get started, we should mention two details. First, the method we’ll
2424
use won’t be the best way to build a web server with Rust. Community members
25-
have published a number of production-ready crates available on
25+
have published a number of production-ready crates available at
2626
[crates.io](https://crates.io/) that provide more complete web server and thread
2727
pool implementations than we’ll build. However, our intention in this chapter is
2828
to help you learn, not to take the easy route. Because Rust is a systems

src/ch21-01-single-threaded.md

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Using `TcpListener`, we can listen for TCP connections at the address
4646
`127.0.0.1:7878`. In the address, the section before the colon is an IP address
4747
representing your computer (this is the same on every computer and doesn’t
4848
represent the authors’ computer specifically), and `7878` is the port. We’ve
49-
chosen this port for two reasons: HTTP isn’t normally accepted on this port so
49+
chosen this port for two reasons: HTTP isn’t normally accepted on this port, so
5050
our server is unlikely to conflict with any other web server you might have
5151
running on your machine, and 7878 is _rust_ typed on a telephone.
5252

@@ -56,14 +56,11 @@ because, in networking, connecting to a port to listen to is known as “binding
5656
to a port.”
5757

5858
The `bind` function returns a `Result<T, E>`, which indicates that it’s
59-
possible for binding to fail. For example, connecting to port 80 requires
60-
administrator privileges (non-administrators can listen only on ports higher
61-
than 1023), so if we tried to connect to port 80 without being an
62-
administrator, binding wouldn’t work. Binding also wouldn’t work, for example,
63-
if we ran two instances of our program and so had two programs listening to the
64-
same port. Because we’re writing a basic server just for learning purposes, we
65-
won’t worry about handling these kinds of errors; instead, we use `unwrap` to
66-
stop the program if errors happen.
59+
possible for binding to fail. For example, if we ran two instances of our
60+
program and so had two programs listening to the same port. Because we’re
61+
writing a basic server just for learning purposes, we won’t worry about
62+
handling these kinds of errors; instead, we use `unwrap` to stop the program if
63+
errors happen.
6764

6865
The `incoming` method on `TcpListener` returns an iterator that gives us a
6966
sequence of streams (more specifically, streams of type `TcpStream`). A single
@@ -112,16 +109,16 @@ part of the `drop` implementation. Browsers sometimes deal with closed
112109
connections by retrying, because the problem might be temporary.
113110

114111
Browsers also sometimes open multiple connections to the server without sending
115-
any requests, so that if they *do* later send requests, they can happen faster.
116-
When this happens, our server will see each connection, regardless of whether
117-
there are any requests over that connection. Many versions of Chrome-based
118-
browsers do this, for example; you can disable that optimization by using =
119-
private browsing mode or use a different browser.
112+
any requests, so that if they *do* later send requests, those requests can
113+
happen faster. When this happens, our server will see each connection,
114+
regardless of whether there are any requests over that connection. Many
115+
versions of Chrome-based browsers do this, for example; you can disable that
116+
optimization by using private browsing mode or using a different browser.
120117

121118
The important factor is that we’ve successfully gotten a handle to a TCP
122119
connection!
123120

124-
Remember to stop the program by pressing <kbd>ctrl</kbd>-<kbd>c</kbd> when
121+
Remember to stop the program by pressing <kbd>ctrl</kbd>-<kbd>C</kbd> when
125122
you’re done running a particular version of the code. Then restart the program
126123
by invoking the `cargo run` command after you’ve made each set of code changes
127124
to make sure you’re running the newest code.
@@ -150,8 +147,8 @@ connection, we now call the new `handle_connection` function and pass the
150147
`stream` to it.
151148

152149
In the `handle_connection` function, we create a new `BufReader` instance that
153-
wraps a reference to the `stream`. The `BufReader` adds buffering by managing calls
154-
to the `std::io::Read` trait methods for us.
150+
wraps a reference to the `stream`. The `BufReader` adds buffering by managing
151+
calls to the `std::io::Read` trait methods for us.
155152

156153
We create a variable named `http_request` to collect the lines of the request
157154
the browser sends to our server. We indicate that we want to collect these
@@ -229,7 +226,7 @@ The next part of the request line is _/_, which indicates the _uniform resource
229226
identifier_ _(URI)_ the client is requesting: a URI is almost, but not quite,
230227
the same as a _uniform resource locator_ _(URL)_. The difference between URIs
231228
and URLs isn’t important for our purposes in this chapter, but the HTTP spec
232-
uses the term URI, so we can just mentally substitute _URL_ for _URI_ here.
229+
uses the term _URI_, so we can just mentally substitute _URL_ for _URI_ here.
233230

234231
The last part is the HTTP version the client uses, and then the request line
235232
ends in a CRLF sequence. (CRLF stands for _carriage return_ and _line feed_,
@@ -354,7 +351,7 @@ request to _/_.
354351

355352
Right now, our web server will return the HTML in the file no matter what the
356353
client requested. Let’s add functionality to check that the browser is
357-
requesting _/_ before returning the HTML file and return an error if the
354+
requesting _/_ before returning the HTML file, and return an error if the
358355
browser requests anything else. For this we need to modify `handle_connection`,
359356
as shown in Listing 21-6. This new code checks the content of the request
360357
received against what we know a request for _/_ looks like and adds `if` and
@@ -404,7 +401,7 @@ indicating the response to the end user.
404401
Here, our response has a status line with status code 404 and the reason phrase
405402
`NOT FOUND`. The body of the response will be the HTML in the file _404.html_.
406403
You’ll need to create a _404.html_ file next to _hello.html_ for the error
407-
page; again feel free to use any HTML you want or use the example HTML in
404+
page; again feel free to use any HTML you want, or use the example HTML in
408405
Listing 21-8.
409406

410407
<Listing number="21-8" file-name="404.html" caption="Sample content for the page to send back with any 404 response">

0 commit comments

Comments
 (0)