1//! An UDP echo server that just sends back everything that it receives.
2//!
3//! If you're on Unix you can test this out by in one terminal executing:
4//!
5//! cargo run --example echo-udp
6//!
7//! and in another terminal you can run:
8//!
9//! cargo run --example connect -- --udp 127.0.0.1:8080
10//!
11//! Each line you type in to the `nc` terminal should be echo'd back to you!
12
13#![warn(rust_2018_idioms)]
14
15use std::error::Error;
16use std::net::SocketAddr;
17use std::{env, io};
18use tokio::net::UdpSocket;
19
20struct Server {
21 socket: UdpSocket,
22 buf: Vec<u8>,
23 to_send: Option<(usize, SocketAddr)>,
24}
25
26impl Server {
27 async fn run(self) -> Result<(), io::Error> {
28 let Server {
29 socket,
30 mut buf,
31 mut to_send,
32 } = self;
33
34 loop {
35 // First we check to see if there's a message we need to echo back.
36 // If so then we try to send it back to the original source, waiting
37 // until it's writable and we're able to do so.
38 if let Some((size, peer)) = to_send {
39 let amt = socket.send_to(&buf[..size], &peer).await?;
40
41 println!("Echoed {}/{} bytes to {}", amt, size, peer);
42 }
43
44 // If we're here then `to_send` is `None`, so we take a look for the
45 // next message we're going to echo back.
46 to_send = Some(socket.recv_from(&mut buf).await?);
47 }
48 }
49}
50
51#[tokio::main]
52async fn main() -> Result<(), Box<dyn Error>> {
53 let addr = env::args()
54 .nth(1)
55 .unwrap_or_else(|| "127.0.0.1:8080".to_string());
56
57 let socket = UdpSocket::bind(&addr).await?;
58 println!("Listening on: {}", socket.local_addr()?);
59
60 let server = Server {
61 socket,
62 buf: vec![0; 1024],
63 to_send: None,
64 };
65
66 // This starts the server task.
67 server.run().await?;
68
69 Ok(())
70}
71