1 | //! A UDP client that just sends everything it gets via `stdio` in a single datagram, and then |
2 | //! waits for a reply. |
3 | //! |
4 | //! For the reasons of simplicity data from `stdio` is read until `EOF` in a blocking manner. |
5 | //! |
6 | //! You can test this out by running an echo server: |
7 | //! |
8 | //! ``` |
9 | //! $ cargo run --example echo-udp -- 127.0.0.1:8080 |
10 | //! ``` |
11 | //! |
12 | //! and running the client in another terminal: |
13 | //! |
14 | //! ``` |
15 | //! $ cargo run --example udp-client |
16 | //! ``` |
17 | //! |
18 | //! You can optionally provide any custom endpoint address for the client: |
19 | //! |
20 | //! ``` |
21 | //! $ cargo run --example udp-client -- 127.0.0.1:8080 |
22 | //! ``` |
23 | //! |
24 | //! Don't forget to pass `EOF` to the standard input of the client! |
25 | //! |
26 | //! Please mind that since the UDP protocol doesn't have any capabilities to detect a broken |
27 | //! connection the server needs to be run first, otherwise the client will block forever. |
28 | |
29 | #![warn (rust_2018_idioms)] |
30 | |
31 | use std::env; |
32 | use std::error::Error; |
33 | use std::io::{stdin, Read}; |
34 | use std::net::SocketAddr; |
35 | use tokio::net::UdpSocket; |
36 | |
37 | fn get_stdin_data() -> Result<Vec<u8>, Box<dyn std::error::Error>> { |
38 | let mut buf = Vec::new(); |
39 | stdin().read_to_end(&mut buf)?; |
40 | Ok(buf) |
41 | } |
42 | |
43 | #[tokio::main] |
44 | async fn main() -> Result<(), Box<dyn Error>> { |
45 | let remote_addr: SocketAddr = env::args() |
46 | .nth(1) |
47 | .unwrap_or_else(|| "127.0.0.1:8080" .into()) |
48 | .parse()?; |
49 | |
50 | // We use port 0 to let the operating system allocate an available port for us. |
51 | let local_addr: SocketAddr = if remote_addr.is_ipv4() { |
52 | "0.0.0.0:0" |
53 | } else { |
54 | "[::]:0" |
55 | } |
56 | .parse()?; |
57 | |
58 | let socket = UdpSocket::bind(local_addr).await?; |
59 | const MAX_DATAGRAM_SIZE: usize = 65_507; |
60 | socket.connect(&remote_addr).await?; |
61 | let data = get_stdin_data()?; |
62 | socket.send(&data).await?; |
63 | let mut data = vec![0u8; MAX_DATAGRAM_SIZE]; |
64 | let len = socket.recv(&mut data).await?; |
65 | println!( |
66 | "Received {} bytes: \n{}" , |
67 | len, |
68 | String::from_utf8_lossy(&data[..len]) |
69 | ); |
70 | |
71 | Ok(()) |
72 | } |
73 | |