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 | |