Files
tokio/examples/echo-udp.rs
T

75 lines
2.2 KiB
Rust
Raw Normal View History

2016-11-01 22:44:25 -07:00
//! An UDP echo server that just sends back everything that it receives.
2016-11-02 16:57:27 -07:00
//!
2018-08-25 15:26:41 -04:00
//! If you're on Unix you can test this out by in one terminal executing:
2016-11-02 16:57:27 -07:00
//!
2016-11-22 12:35:30 -08:00
//! cargo run --example echo-udp
2016-11-02 16:57:27 -07:00
//!
//! and in another terminal you can run:
//!
2017-09-11 08:32:34 -07:00
//! cargo run --example connect -- --udp 127.0.0.1:8080
2016-11-02 16:57:27 -07:00
//!
//! Each line you type in to the `nc` terminal should be echo'd back to you!
2016-11-01 22:44:25 -07:00
#![deny(warnings)]
#[macro_use]
2016-11-01 22:44:25 -07:00
extern crate futures;
2017-10-24 16:30:16 -07:00
extern crate tokio;
2016-11-01 22:44:25 -07:00
use std::{env, io};
use std::net::SocketAddr;
use tokio::prelude::*;
2017-10-24 16:30:16 -07:00
use tokio::net::UdpSocket;
2016-11-01 22:44:25 -07:00
struct Server {
2016-11-02 16:57:27 -07:00
socket: UdpSocket,
buf: Vec<u8>,
to_send: Option<(usize, SocketAddr)>,
2016-11-01 22:44:25 -07:00
}
impl Future for Server {
type Item = ();
type Error = io::Error;
fn poll(&mut self) -> Poll<(), io::Error> {
loop {
2016-11-02 16:57:27 -07:00
// First we check to see if there's a message we need to echo back.
// If so then we try to send it back to the original source, waiting
2017-03-07 11:39:51 +08:00
// until it's writable and we're able to do so.
2016-11-02 16:57:27 -07:00
if let Some((size, peer)) = self.to_send {
let amt = try_ready!(self.socket.poll_send_to(&self.buf[..size], &peer));
2016-11-02 16:57:27 -07:00
println!("Echoed {}/{} bytes to {}", amt, size, peer);
self.to_send = None;
2016-11-01 22:44:25 -07:00
}
2016-11-02 16:57:27 -07:00
// If we're here then `to_send` is `None`, so we take a look for the
// next message we're going to echo back.
self.to_send = Some(try_ready!(self.socket.poll_recv_from(&mut self.buf)));
2016-11-01 22:44:25 -07:00
}
}
}
fn main() -> Result<(), Box<std::error::Error>> {
2016-11-01 22:44:25 -07:00
let addr = env::args().nth(1).unwrap_or("127.0.0.1:8080".to_string());
let addr = addr.parse::<SocketAddr>()?;
2016-11-01 22:44:25 -07:00
let socket = UdpSocket::bind(&addr)?;
println!("Listening on: {}", socket.local_addr()?);
2016-11-01 22:44:25 -07:00
let server = Server {
2016-11-02 16:57:27 -07:00
socket: socket,
buf: vec![0; 1024],
to_send: None,
};
// This starts the server task.
//
// `map_err` handles the error by logging it and maps the future to a type
// that can be spawned.
//
2018-05-08 14:44:17 -04:00
// `tokio::run` spawns the task on the Tokio runtime and starts running.
tokio::run(server.map_err(|e| println!("server error = {:?}", e)));
Ok(())
2016-11-01 22:44:25 -07:00
}