Skip to content

Commit

Permalink
getting started rewrite + intro to tokio features (#394)
Browse files Browse the repository at this point in the history
1. simplify "hello world"
- use socat which hopefully doesn't have the same cross-platform issues as we were running into with netcat
- intro network utils first (which also provides a gentle intro to networking)
- app wasn't using io so removed from text
- adjust text to describe hello-world as a client app (since that's what it is)
- new page: intro to feature dependencies. The idea is to just walk through the few feature that are used in the "hello world" app so that people understand the concept.

2. outline the reasons why to use features=full or select specific features.
Later we'd like to add a topic page that goes into more detail about all of the feature groupings, and this page would then link to that (or we could even make this into a smaller call out when we have that complete info). -- #401 for feature topic page

3. Network utilities section -- this is a bit bare bones right now. I didn't feel good about using anything in the guide without install instructions and it's a bit verbose without instructions. -- open issue for x-platform testing and maybe using nc instead of telnet #407

Co-authored-by: Jen-Mei Wu <[email protected]>
  • Loading branch information
ultrasaurus and jenmei authored Jan 14, 2020
1 parent 39fc4b6 commit c1151f0
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 108 deletions.
3 changes: 3 additions & 0 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ menu:
name: "API documentation"
url: "https://docs.rs/tokio"
weight: 9000
- identifier: "network_utils"
name: "Network Utilities"
weight: 10000


params:
Expand Down
136 changes: 136 additions & 0 deletions content/docs/getting-started/cargo-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
---
title: "Cargo dependencies"
weight : 1020
menu:
docs:
parent: getting_started
---

Feel free to skip this section, and just use `features = ["full"]` while
learning. This section provides some examples of how and when to choose
specific [`feature groups`] in `Cargo.toml`.

## Often using all features is fine

When writing an app, we'll often use all of Tokio's features to accelerate
our development time.

Cargo.toml:
```toml
[dependencies]
tokio = { version = "0.2", features = ["full"] }
```

For most apps, the additional compile time is hardly noticeable relative to the
cognitive overhead of thinking about which features are needed.

# Selecting features

When we develop protocol implementations that are used by client apps and
servers, we want to limit the dependencies to decrease compile time --
not just for us, but also for the users of our crates.

Let's take a look at our tiny client app and see what features are needed.

## tokio main

If we replace our `src/main.rs` with following code (only adding the
`#[tokio:main]` macro to the default hello world generated by `cargo new`):

main.rs:
```rust
#[tokio::main]
async fn main() {
println!("doing nothing yet");
}
```

Then we can choose whether to use threads (commonly used for servers):

```toml
tokio = { version = "0.2", features = ["macros", "rt-threaded"] }
```

or lightweight cooperative multi-tasking
(often required for low-profile clients):

```toml
tokio = { version = "0.2", features = ["macros", "rt-core"] }
```

## TcpStream connect

As we start to build the app, we'll need more features. The line of code
where we call `TcpStream::connect` requires two features:


```rust,no_run
# #![deny(deprecated)]
# #![allow(unused_mut)]
# #![allow(unused_variables)]
# use tokio::net::TcpStream;
# #[tokio::main]
# async fn main() {
let mut stream = TcpStream::connect("127.0.0.1:6142").await.unwrap();
# }
```


1. `dns` for converting the string `127.0.0.1:6142` to an IP address -- Tokio
will need to do a DNS lookup just in case.
2. `tcp` for handling the TCP connection


Since our example uses a specific ip address, we can reduce dependendencies
further by creating a [`std::net::SocketAddr`]:

```rust,no_run
# #![deny(deprecated)]
# #![allow(unused_mut)]
# #![allow(unused_variables)]
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use tokio::net::TcpStream;
#[tokio::main]
async fn main() {
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 6142);
let mut stream = TcpStream::connect(addr).await;
}
```

## Writing to the socket

The `write` method is defined in [`tokio::io::AsyncWriteExt`] which requires
`io-util`.

```rust,no_run
# #![deny(deprecated)]
# #![allow(unused_variables)]
# use tokio::net::TcpStream;
# use tokio::prelude::*;
# #[tokio::main]
# async fn main() {
# let mut stream = TcpStream::connect("127.0.0.1:6142").await.unwrap();
let result = stream.write(b"hello world\n").await;
# }
```

The `write` method in our example is declared with `use tokio::prelude::*`.
The [`tokio prelude`] follows the [`Rust prelude pattern`] to make using
multiple types more convenient. We could be more explicit by declaring `use tokio::io::AsyncWriteExt`:


## Learn more about features

The [`API reference`] indicates which features are need for different APIs.
If anything missing, please [`open an issue`] and one of the Tokio elves
will figure out where it is declared and will fix it asap!

[`feature groups`]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section
[`std::net::SocketAddr`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html
[`tokio::io::AsyncWriteExt`]: https://docs.rs/tokio/*/tokio/io/trait.AsyncWriteExt.html
[`tokio prelude`]: https://docs.rs/tokio/0.2.9/tokio/prelude/index.html
[`Rust prelude pattern`]: https://doc.rust-lang.org/std/prelude/index.html#other-preludes
[`API reference`]: https://docs.rs/tokio/
[`open an issue`]: https://github.com/tokio-rs/tokio/issues/new
Loading

0 comments on commit c1151f0

Please sign in to comment.