diff --git a/Cargo.toml b/Cargo.toml index ae0b605e..12aa5a71 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ members = [ "tls", "rustls", "unix-socket", + "udp-echo", "web-cors/backend", "websocket", "websocket-chat", diff --git a/udp-echo/Cargo.toml b/udp-echo/Cargo.toml new file mode 100644 index 00000000..8174deab --- /dev/null +++ b/udp-echo/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "udp-echo" +version = "0.1.0" +authors = ["Anton Patrushev "] +edition = "2018" + +[dependencies] +actix = "0.7" +tokio = "*" +futures = "*" +bytes = "*" diff --git a/udp-echo/README.md b/udp-echo/README.md new file mode 100644 index 00000000..a72dd5da --- /dev/null +++ b/udp-echo/README.md @@ -0,0 +1,18 @@ +# udp-echo + +## Usage + +### server + +```bash +cd examples/udp-echo +cargo run +# Started http server: 127.0.0.1:12345 +``` + +### socat client +Copy port provided in server output and run following command to communicate +with the udp server: +```bash +socat - UDP4:localhost:12345 +``` diff --git a/udp-echo/src/main.rs b/udp-echo/src/main.rs new file mode 100644 index 00000000..c3406a5d --- /dev/null +++ b/udp-echo/src/main.rs @@ -0,0 +1,47 @@ +extern crate actix; +extern crate bytes; +extern crate futures; +extern crate tokio; + +use actix::{Actor, AsyncContext, Context, Message, StreamHandler}; +use bytes::BytesMut; +use futures::stream::SplitSink; +use futures::{Future, Sink, Stream}; +use std::net::SocketAddr; +use tokio::codec::BytesCodec; +use tokio::net::{UdpFramed, UdpSocket}; + +struct UdpActor { + sink: SplitSink>, +} +impl Actor for UdpActor { + type Context = Context; +} + +#[derive(Message)] +struct UdpPacket(BytesMut, SocketAddr); +impl StreamHandler for UdpActor { + fn handle(&mut self, msg: UdpPacket, _: &mut Context) { + println!("Received: ({:?}, {:?})", msg.0, msg.1); + (&mut self.sink).send((msg.0.into(), msg.1)).wait().unwrap(); + } +} + +fn main() { + let sys = actix::System::new("echo-udp"); + + let addr: SocketAddr = "127.0.0.1:0".parse().unwrap(); + let sock = UdpSocket::bind(&addr).unwrap(); + println!( + "Started udp server on: 127.0.0.1:{:?}", + sock.local_addr().unwrap().port() + ); + + let (sink, stream) = UdpFramed::new(sock, BytesCodec::new()).split(); + UdpActor::create(|ctx| { + ctx.add_stream(stream.map(|(data, sender)| UdpPacket(data, sender))); + UdpActor { sink: sink } + }); + + std::process::exit(sys.run()); +}