Reputation: 1975
So far the only example I have found is the single threaded example Echo UDP from the Tokio repository. How does one start a loop with Tokio that will spawn a new thread to handle new UDP connections.
Upvotes: 2
Views: 6687
Reputation: 432199
How does one set up Tokio 0.2 to “listen” for UDP data?
use tokio::net::UdpSocket; // "0.2.20", features = ["full"]
type Error = Box<dyn std::error::Error>;
type Result<T, E = Error> = std::result::Result<T, E>;
#[tokio::main]
async fn main() -> Result<()> {
let mut socket = UdpSocket::bind("127.0.0.1:9999").await?;
loop {
let mut data = [0; 1024];
let valid_bytes = socket.recv(&mut data).await?;
let data = &data[..valid_bytes];
eprintln!("Read {} bytes", data.len());
}
}
(The code is effectively identical for Tokio 1.4, just remove the mut
qualifier.)
In one window:
% cargo run
Read 6 bytes
Read 5 bytes
Read 6 bytes
In another:
% nc -u 127.0.0.1 9999
alpha
beta
gamma
How to set up Tokio as a multi-threaded UDP server?
The code above is multi threaded; Tokio is multithreaded by default. You may be looking to create concurrent (and possibly parallel) work; That can be done via spawning a task:
Upvotes: 2
Reputation: 1819
To create a schedulable unit in tokio you should use tokio::task::spawn
. If underlying runtime is multithreaded then these units will be completed by multiple threads.
You can see how it works by adding a couple of lines to the example
fn main() {
...
let jh = tokio::task::spawn(server.run());
println!("udp server started {:?}", std::thread::current().id());
jh.await?;
...
}
fn run
...
loop {
if let Some((size, peer)) = to_send {
let amt = socket.send_to(&buf[..size], &peer).await?;
println!("eched back {:?}", std::thread::current().id());
}
to_send = Some(socket.recv_from(&mut buf).await?);
println!("read some stuff {:?}", std::thread::current().id());
}
Upvotes: 2