2018-03-22 18:00:28 +01:00
|
|
|
//! 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.
|
|
|
|
|
|
2019-08-10 00:07:57 +09:00
|
|
|
#![warn(rust_2018_idioms)]
|
2018-03-22 18:00:28 +01:00
|
|
|
|
|
|
|
|
use std::env;
|
2019-07-25 16:47:31 -04:00
|
|
|
use std::error::Error;
|
2019-07-09 20:21:12 +02:00
|
|
|
use std::io::{stdin, Read};
|
2018-03-22 18:00:28 +01:00
|
|
|
use std::net::SocketAddr;
|
|
|
|
|
use tokio::net::UdpSocket;
|
|
|
|
|
|
2019-05-14 10:27:36 -07:00
|
|
|
fn get_stdin_data() -> Result<Vec<u8>, Box<dyn std::error::Error>> {
|
2018-03-22 18:00:28 +01:00
|
|
|
let mut buf = Vec::new();
|
2018-11-20 18:10:36 +02:00
|
|
|
stdin().read_to_end(&mut buf)?;
|
|
|
|
|
Ok(buf)
|
2018-03-22 18:00:28 +01:00
|
|
|
}
|
|
|
|
|
|
2019-07-09 20:21:12 +02:00
|
|
|
#[tokio::main]
|
2019-07-25 16:47:31 -04:00
|
|
|
async fn main() -> Result<(), Box<dyn Error>> {
|
2018-03-22 18:00:28 +01:00
|
|
|
let remote_addr: SocketAddr = env::args()
|
|
|
|
|
.nth(1)
|
2019-12-14 09:01:47 +03:00
|
|
|
.unwrap_or_else(|| "127.0.0.1:8080".into())
|
2019-07-25 16:47:31 -04:00
|
|
|
.parse()?;
|
2019-07-10 11:21:06 -07:00
|
|
|
|
2018-03-22 18:00:28 +01:00
|
|
|
// 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"
|
2019-02-21 11:56:15 -08:00
|
|
|
}
|
2019-07-25 16:47:31 -04:00
|
|
|
.parse()?;
|
2019-07-10 11:21:06 -07:00
|
|
|
|
2020-09-23 13:02:15 -07:00
|
|
|
let socket = UdpSocket::bind(local_addr).await?;
|
2018-03-22 18:00:28 +01:00
|
|
|
const MAX_DATAGRAM_SIZE: usize = 65_507;
|
2019-08-28 13:25:50 -07:00
|
|
|
socket.connect(&remote_addr).await?;
|
2019-07-25 16:47:31 -04:00
|
|
|
let data = get_stdin_data()?;
|
|
|
|
|
socket.send(&data).await?;
|
2019-07-09 20:21:12 +02:00
|
|
|
let mut data = vec![0u8; MAX_DATAGRAM_SIZE];
|
2019-07-25 16:47:31 -04:00
|
|
|
let len = socket.recv(&mut data).await?;
|
2019-07-09 20:21:12 +02:00
|
|
|
println!(
|
|
|
|
|
"Received {} bytes:\n{}",
|
|
|
|
|
len,
|
|
|
|
|
String::from_utf8_lossy(&data[..len])
|
|
|
|
|
);
|
2019-07-25 16:47:31 -04:00
|
|
|
|
|
|
|
|
Ok(())
|
2018-03-22 18:00:28 +01:00
|
|
|
}
|