mallwright
mallwright

Reputation: 1975

How to set up Tokio as a multi-threaded UDP server?

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

Answers (2)

Shepmaster
Shepmaster

Reputation: 432199

Answer for the original version of the question

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

Answer for the current version of the question

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

ekim boran
ekim boran

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

Related Questions