到目前为止,我找到的唯一一个例子就是单线程的例子。回声UDP 从 Tokio 仓库中取出。如何用 Tokio 启动一个循环,产生一个新的线程来处理新的 UDP 连接。
如何设置Tokio 0.2 "监听 "UDP数据?
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());
}
}
在一个窗口中。
% cargo run
Read 6 bytes
Read 5 bytes
Read 6 bytes
在另一个窗口
% nc -u 127.0.0.1 9999
alpha
beta
gamma
如何将Tokio设置为多线程UDP服务器?
上面的代码 是 多线程。Tokio默认是多线程的. 您可能希望创建并发(可能是并行)工作;这可以通过 生成任务:
要在tokio中创建一个可调度的单位,你应该使用以下方法 tokio::task::spawn
. 如果底层运行时是多线程的,那么这些单元将由多个线程完成。
你可以通过在示例中添加几行来了解它是如何工作的。
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());
}