Files
tokio/examples/udp-codec.rs
T

65 lines
2.2 KiB
Rust
Raw Normal View History

//! This example leverages `BytesCodec` to create a UDP client and server which
//! speak a custom protocol.
2016-11-22 12:35:30 -08:00
//!
2018-02-07 01:41:31 +04:00
//! Here we're using the codec from tokio-io to convert a UDP socket to a stream of
2016-11-22 12:35:30 -08:00
//! client messages. These messages are then processed and returned back as a
//! new message with a new destination. Overall, we then use this to construct a
//! "ping pong" pair where two sockets are sending messages back and forth.
#![deny(warnings)]
2017-10-24 16:30:16 -07:00
extern crate tokio;
2018-06-04 22:36:06 -05:00
extern crate tokio_codec;
2018-02-07 01:41:31 +04:00
extern crate tokio_io;
extern crate env_logger;
2016-11-22 12:35:30 -08:00
use std::net::SocketAddr;
use tokio::prelude::*;
2018-02-07 10:42:27 -08:00
use tokio::net::{UdpSocket, UdpFramed};
2018-06-04 22:36:06 -05:00
use tokio_codec::BytesCodec;
fn main() {
let _ = env_logger::init();
2017-10-25 10:54:54 -07:00
2016-11-22 12:35:30 -08:00
let addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
// Bind both our sockets and then figure out what ports we got.
let a = UdpSocket::bind(&addr).unwrap();
let b = UdpSocket::bind(&addr).unwrap();
2016-11-22 12:35:30 -08:00
let b_addr = b.local_addr().unwrap();
2018-03-12 10:39:32 -07:00
// We're parsing each socket with the `BytesCodec` included in `tokio_io`, and then we
2016-11-22 12:35:30 -08:00
// `split` each codec into the sink/stream halves.
2018-02-07 10:42:27 -08:00
let (a_sink, a_stream) = UdpFramed::new(a, BytesCodec::new()).split();
let (b_sink, b_stream) = UdpFramed::new(b, BytesCodec::new()).split();
2016-11-22 12:35:30 -08:00
// Start off by sending a ping from a to b, afterwards we just print out
// what they send us and continually send pings
// let pings = stream::iter((0..5).map(Ok));
2018-02-07 01:41:31 +04:00
let a = a_sink.send(("PING".into(), b_addr)).and_then(|a_sink| {
2016-11-22 12:35:30 -08:00
let mut i = 0;
2018-02-07 01:41:31 +04:00
let a_stream = a_stream.take(4).map(move |(msg, addr)| {
2016-11-22 12:35:30 -08:00
i += 1;
println!("[a] recv: {}", String::from_utf8_lossy(&msg));
2018-02-07 01:41:31 +04:00
(format!("PING {}", i).into(), addr)
2016-11-22 12:35:30 -08:00
});
a_sink.send_all(a_stream)
});
// The second client we have will receive the pings from `a` and then send
// back pongs.
2018-02-07 01:41:31 +04:00
let b_stream = b_stream.map(|(msg, addr)| {
2016-11-22 12:35:30 -08:00
println!("[b] recv: {}", String::from_utf8_lossy(&msg));
2018-02-07 01:41:31 +04:00
("PONG".into(), addr)
2016-11-22 12:35:30 -08:00
});
let b = b_sink.send_all(b_stream);
// Spawn the sender of pongs and then wait for our pinger to finish.
tokio::run({
b.join(a)
.map(|_| ())
.map_err(|e| println!("error = {:?}", e))
});
}