summaryrefslogtreecommitdiffstats
path: root/examples/udp-client.rs
diff options
context:
space:
mode:
authorCarl Lerche <me@carllerche.com>2019-10-22 10:13:49 -0700
committerGitHub <noreply@github.com>2019-10-22 10:13:49 -0700
commitcfc15617a5247ea780c32c85b7134b88b6de5845 (patch)
treeef0a46c61c51505a60f386c9760acac9d1f9b7b1 /examples/udp-client.rs
parentb8cee1a60ad99ef28ec494ae4230e2ef4399fcf9 (diff)
codec: move into tokio-util (#1675)
Related to #1318, Tokio APIs that are "less stable" are moved into a new `tokio-util` crate. This crate will mirror `tokio` and provide additional APIs that may require a greater rate of breaking changes. As examples require `tokio-util`, they are moved into a separate crate (`examples`). This has the added advantage of being able to avoid example only dependencies in the `tokio` crate.
Diffstat (limited to 'examples/udp-client.rs')
-rw-r--r--examples/udp-client.rs72
1 files changed, 72 insertions, 0 deletions
diff --git a/examples/udp-client.rs b/examples/udp-client.rs
new file mode 100644
index 00000000..5437daf6
--- /dev/null
+++ b/examples/udp-client.rs
@@ -0,0 +1,72 @@
+//! A UDP client that just sends everything it gets via `stdio` in a single datagram, and then
+//! waits for a reply.
+//!
+//! For the reasons of simplicity data from `stdio` is read until `EOF` in a blocking manner.
+//!
+//! You can test this out by running an echo server:
+//!
+//! ```
+//! $ cargo run --example echo-udp -- 127.0.0.1:8080
+//! ```
+//!
+//! and running the client in another terminal:
+//!
+//! ```
+//! $ cargo run --example udp-client
+//! ```
+//!
+//! You can optionally provide any custom endpoint address for the client:
+//!
+//! ```
+//! $ cargo run --example udp-client -- 127.0.0.1:8080
+//! ```
+//!
+//! Don't forget to pass `EOF` to the standard input of the client!
+//!
+//! Please mind that since the UDP protocol doesn't have any capabilities to detect a broken
+//! connection the server needs to be run first, otherwise the client will block forever.
+
+#![warn(rust_2018_idioms)]
+
+use std::env;
+use std::error::Error;
+use std::io::{stdin, Read};
+use std::net::SocketAddr;
+use tokio::net::UdpSocket;
+
+fn get_stdin_data() -> Result<Vec<u8>, Box<dyn std::error::Error>> {
+ let mut buf = Vec::new();
+ stdin().read_to_end(&mut buf)?;
+ Ok(buf)
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn Error>> {
+ let remote_addr: SocketAddr = env::args()
+ .nth(1)
+ .unwrap_or("127.0.0.1:8080".into())
+ .parse()?;
+
+ // We use port 0 to let the operating system allocate an available port for us.
+ let local_addr: SocketAddr = if remote_addr.is_ipv4() {
+ "0.0.0.0:0"
+ } else {
+ "[::]:0"
+ }
+ .parse()?;
+
+ let mut socket = UdpSocket::bind(local_addr).await?;
+ const MAX_DATAGRAM_SIZE: usize = 65_507;
+ socket.connect(&remote_addr).await?;
+ let data = get_stdin_data()?;
+ socket.send(&data).await?;
+ let mut data = vec![0u8; MAX_DATAGRAM_SIZE];
+ let len = socket.recv(&mut data).await?;
+ println!(
+ "Received {} bytes:\n{}",
+ len,
+ String::from_utf8_lossy(&data[..len])
+ );
+
+ Ok(())
+}