Skip to content

Commit 29dbbe5

Browse files
committed
Dockerfiles for Ch 04
Since Mac (and to a lesser extent Windows, though it has WSL) cannot work with epoll directly, Dockerfiles, Docker compose yml, and simple run scripts have been created so that users who have docker can run and test the ch04 examples on their system. A docker file has been created for delayserver as well and docker compose is used to run an epoll container and a delay server container and coordinate the network between them. Some slight modification has been made to the epoll code to allow for an optional argument to be passed in which is the name of the host. When running the examples without docker both are running on "localhost". However when running docker containers epoll and delayserver are in separate containers, so epoll needs to transmit to the delayserver container (conveniently named "delayserver") instead of localhost. Debian slim rust containers have been used as they are a convenient and fairly small container for these kinds of rust projects. README.md's have been updated to note that it is now possible to pass an optional argument for the hostname to connect to, which will default to "localhost" if no argument is passed.
1 parent fa40c92 commit 29dbbe5

File tree

13 files changed

+130
-19
lines changed

13 files changed

+130
-19
lines changed

ch04/a-epoll/Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM rust:1-slim-bookworm
2+
3+
WORKDIR /usr/a-epoll
4+
5+
COPY . .
6+
7+
RUN cargo build
8+
9+
CMD ["cargo", "run", "delayserver"]

ch04/a-epoll/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ additional comments that's not in the book.
55

66
You can run the example by simply writing `cargo run`
77

8+
If running on a Mac system (which only supports kqueue but not epoll), docker
9+
can be used to run the example by running the epoll_docker.sh script
10+
811
## Note
912

1013
There is one downside of having a local server on the same machine to mimic

ch04/a-epoll/docker-compose.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
services:
2+
delayserver:
3+
build: ../../delayserver/
4+
ports:
5+
- "8080:8080"
6+
networks:
7+
- delayserver_network
8+
9+
epoll:
10+
build: .
11+
depends_on:
12+
- delayserver
13+
networks:
14+
- delayserver_network
15+
16+
networks:
17+
delayserver_network: {}

ch04/a-epoll/epoll_docker.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
docker compose up --build

ch04/a-epoll/src/main.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::{
1717
collections::HashSet,
1818
io::{self, Read, Result, Write},
1919
net::TcpStream,
20+
env
2021
};
2122

2223
use ffi::Event;
@@ -84,13 +85,21 @@ fn main() -> Result<()> {
8485
let n_events = 5;
8586

8687
let mut streams = vec![];
87-
let addr = "localhost:8080";
88+
89+
let args: Vec<String> = env::args().collect();
90+
let base_url;
91+
if args.len() > 1 {
92+
base_url = args[1].clone();
93+
} else {
94+
base_url = String::from("localhost");
95+
}
96+
let addr = format!("{}:8080", &base_url);
8897

8998
for i in 0..n_events {
9099
let delay = (n_events - i) * 1000;
91100
let url_path = format!("/{delay}/request-{i}");
92101
let request = get_req(&url_path);
93-
let mut stream = std::net::TcpStream::connect(addr)?;
102+
let mut stream = std::net::TcpStream::connect(&addr)?;
94103
stream.set_nonblocking(true)?;
95104

96105
stream.write_all(request.as_bytes())?;

ch04/b-epoll-mio/Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM rust:1-slim-bookworm
2+
3+
WORKDIR /usr/a-epoll
4+
5+
COPY . .
6+
7+
RUN cargo build
8+
9+
CMD ["cargo", "run", "delayserver"]

ch04/b-epoll-mio/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
# a-epoll-mio
1+
# b-epoll-mio
22

33
This create contains the example code for chapter 4, but instead of using
44
our own queue, we use one created by [mio](https://github.com/tokio-rs/mio). Since we modelled our own code after
55
mio you only need to make a few very minor changes to get it working which I've
66
commented and marked out as clearly as I can.
77

8+
If running on a Mac system (which only supports kqueue but not epoll), docker
9+
can be used to run the example by running the epoll_mio_docker.sh script
10+
811
You can run the example by simply writing `cargo run`
912

1013
## Note

ch04/b-epoll-mio/docker-compose.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
services:
2+
delayserver:
3+
build: ../../delayserver/
4+
ports:
5+
- "8080:8080"
6+
networks:
7+
- delayserver_network
8+
9+
epoll-mio:
10+
build: .
11+
depends_on:
12+
- delayserver
13+
networks:
14+
- delayserver_network
15+
16+
networks:
17+
delayserver_network: {}

ch04/b-epoll-mio/epoll_mio_docker.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
3+
docker compose up --build

ch04/b-epoll-mio/src/main.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! # FIXES:
2-
//!
2+
//!
33
//! The number is identical to the number in the GitHub issue tracker
44
//!
55
//! ## FIX ISSUE #4:
6-
//!
6+
//!
77
//! See:https://github.com/PacktPublishing/Asynchronous-Programming-in-Rust/issues/4
88
//! Some users reported false event notification causing the counter to increase
99
//! due to the OS reporting a READ event after we already read the TcpStream to EOF.
@@ -13,24 +13,25 @@
1313
//! The fix for this is to account for false wakeups which is an easy fix but requires
1414
//! a few changes to the example. I've added an explicit comment: "FIX #4", the places
1515
//! I made a change so it's easy to spot the differences to the example code in the book.
16-
//!
16+
//!
1717
//! ## TROUBLESHOOTING (KNOWN POTENTIAL ISSUE)
18-
//!
18+
//!
1919
//! ### EXAMPLE DOESN'T WORK AS EXPECTED - PROBLEM WITH DNS LOOKUP
2020
//! If you first run this example on Linux under WSL and then immediately run it on
2121
//! Windows, I've observed issues with the DNS lookup for "localhost" being so slow
2222
//! that it defeats the purpose of the example. This issue could potentially also
2323
//! happen under other scenarios than the one mentioned here and the fix will be
2424
//! the same regardless.
25-
//!
26-
//! I don't consider this a bug with our code but a surprising behavior of the
27-
//! WSL/Windows network stack. Anyway, if you encounter this, the fix is simple:
28-
//!
29-
//! Change `let addr = "localhost:8080";` to `let addr = "127.0.0.1:8080";`.
25+
//!
26+
//! I don't consider this a bug with our code but a surprising behavior of the
27+
//! WSL/Windows network stack. Anyway, if you encounter this, the fix is simple:
28+
//!
29+
//! Change `base_url = String::from("localhost");` to `base_url = String::from("127.0.0.1");`.
3030
//!
3131
3232
// FIX #4 (import `HashSet``)
3333
use std::collections::HashSet;
34+
use std::env;
3435
use std::io::{self, Read, Result, Write};
3536

3637
use mio::event::Event;
@@ -91,13 +92,21 @@ fn main() -> Result<()> {
9192
let n_events = 5;
9293

9394
let mut streams = vec![];
94-
let addr = "localhost:8080";
95+
96+
let args: Vec<String> = env::args().collect();
97+
let base_url;
98+
if args.len() > 1 {
99+
base_url = args[1].clone();
100+
} else {
101+
base_url = String::from("localhost");
102+
}
103+
let addr = format!("{}:8080", &base_url);
95104

96105
for i in 0..n_events {
97106
let delay = (n_events - i) * 1000;
98107
let url_path = format!("/{delay}/request-{i}");
99108
let request = get_req(&url_path);
100-
let std_stream = std::net::TcpStream::connect(addr)?;
109+
let std_stream = std::net::TcpStream::connect(&addr)?;
101110
std_stream.set_nonblocking(true)?;
102111

103112
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -117,7 +126,7 @@ fn main() -> Result<()> {
117126

118127
streams.push(stream);
119128
}
120-
129+
121130
// FIX #4: store the handled IDs
122131
let mut handled_ids = HashSet::new();
123132

@@ -139,7 +148,7 @@ fn main() -> Result<()> {
139148
// Events collection
140149
let events: Vec<Event> = events.into_iter().map(|e| e.clone()).collect();
141150
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
142-
151+
143152
// ------------------------------------------------------⌄ FIX #4 (new signature)
144153
handled_events += handle_events(&events, &mut streams, &mut handled_ids)?;
145154
}

delayserver/Dockerfile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
FROM rust:1-slim-bookworm
2+
3+
WORKDIR /usr/delayserver
4+
5+
COPY . .
6+
7+
RUN cargo build
8+
9+
CMD ["cargo", "run", "delayserver"]

delayserver/docker-compose.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
services:
2+
delayserver:
3+
build: .
4+
ports:
5+
- 8080
6+
networks:
7+
- network1
8+
9+
networks:
10+
network1: {}

delayserver/src/main.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
use std::{time::Duration, sync::atomic::{AtomicUsize, Ordering}};
1+
use std::{time::Duration, sync::atomic::{AtomicUsize, Ordering}, env};
22
use actix_web::{Responder, get, HttpServer, App, web, rt::time::sleep};
33

44
const EXPLANATION: &str =
55
"USAGE:
66
Delay server works by issuing a http GET request in the format:
77
http://localhost:8080/[delay in ms]/[UrlEncoded meesage]
88
9+
If an argument is passed in when delayserver is started, that
10+
argument will be used as the url instead of 'localhost'
11+
912
On reception, it immidiately reports the following to the console:
1013
{Message #} - {delay in ms}: {message}
1114
@@ -27,12 +30,19 @@ async fn delay(path: web::Path<(u64, String)>) -> impl Responder {
2730

2831
#[actix_web::main]
2932
async fn main() -> std::io::Result<()> {
33+
let args: Vec<String> = env::args().collect();
34+
let url;
35+
if args.len() > 1 {
36+
url = args[1].clone();
37+
} else {
38+
url = String::from("localhost");
39+
}
3040
println!("{EXPLANATION}");
3141
HttpServer::new(|| {
3242
App::new()
3343
.service(delay)
3444
})
35-
.bind(("127.0.0.1", 8080))?
45+
.bind((url, 8080))?
3646
.run()
3747
.await
38-
}
48+
}

0 commit comments

Comments
 (0)