| 1 | // You can run this example from the root of the mio repo: |
| 2 | // cargo run --example udp_server --features="os-poll net" |
| 3 | use log::warn; |
| 4 | use mio::{Events, Interest, Poll, Token}; |
| 5 | use std::io; |
| 6 | |
| 7 | // A token to allow us to identify which event is for the `UdpSocket`. |
| 8 | const UDP_SOCKET: Token = Token(0); |
| 9 | |
| 10 | #[cfg (not(target_os = "wasi" ))] |
| 11 | fn main() -> io::Result<()> { |
| 12 | use mio::net::UdpSocket; |
| 13 | |
| 14 | env_logger::init(); |
| 15 | |
| 16 | // Create a poll instance. |
| 17 | let mut poll = Poll::new()?; |
| 18 | // Create storage for events. Since we will only register a single socket, a |
| 19 | // capacity of 1 will do. |
| 20 | let mut events = Events::with_capacity(1); |
| 21 | |
| 22 | // Setup the UDP socket. |
| 23 | let addr = "127.0.0.1:9000" .parse().unwrap(); |
| 24 | |
| 25 | let mut socket = UdpSocket::bind(addr)?; |
| 26 | |
| 27 | // Register our socket with the token defined above and an interest in being |
| 28 | // `READABLE`. |
| 29 | poll.registry() |
| 30 | .register(&mut socket, UDP_SOCKET, Interest::READABLE)?; |
| 31 | |
| 32 | println!("You can connect to the server using `nc`:" ); |
| 33 | println!(" $ nc -u 127.0.0.1 9000" ); |
| 34 | println!("Anything you type will be echoed back to you." ); |
| 35 | |
| 36 | // Initialize a buffer for the UDP packet. We use the maximum size of a UDP |
| 37 | // packet, which is the maximum value of 16 a bit integer. |
| 38 | let mut buf = [0; 1 << 16]; |
| 39 | |
| 40 | // Our event loop. |
| 41 | loop { |
| 42 | // Poll to check if we have events waiting for us. |
| 43 | if let Err(err) = poll.poll(&mut events, None) { |
| 44 | if err.kind() == io::ErrorKind::Interrupted { |
| 45 | continue; |
| 46 | } |
| 47 | return Err(err); |
| 48 | } |
| 49 | |
| 50 | // Process each event. |
| 51 | for event in events.iter() { |
| 52 | // Validate the token we registered our socket with, |
| 53 | // in this example it will only ever be one but we |
| 54 | // make sure it's valid none the less. |
| 55 | match event.token() { |
| 56 | UDP_SOCKET => loop { |
| 57 | // In this loop we receive all packets queued for the socket. |
| 58 | match socket.recv_from(&mut buf) { |
| 59 | Ok((packet_size, source_address)) => { |
| 60 | // Echo the data. |
| 61 | socket.send_to(&buf[..packet_size], source_address)?; |
| 62 | } |
| 63 | Err(e) if e.kind() == io::ErrorKind::WouldBlock => { |
| 64 | // If we get a `WouldBlock` error we know our socket |
| 65 | // has no more packets queued, so we can return to |
| 66 | // polling and wait for some more. |
| 67 | break; |
| 68 | } |
| 69 | Err(e) => { |
| 70 | // If it was any other kind of error, something went |
| 71 | // wrong and we terminate with an error. |
| 72 | return Err(e); |
| 73 | } |
| 74 | } |
| 75 | }, |
| 76 | _ => { |
| 77 | // This should never happen as we only registered our |
| 78 | // `UdpSocket` using the `UDP_SOCKET` token, but if it ever |
| 79 | // does we'll log it. |
| 80 | warn!("Got event for unexpected token: {:?}" , event); |
| 81 | } |
| 82 | } |
| 83 | } |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | #[cfg (target_os = "wasi" )] |
| 88 | fn main() { |
| 89 | panic!("can't bind to an address with wasi" ) |
| 90 | } |
| 91 | |