| 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 | |