我正在尝试使用Rust的tokio
停止异步TCP连接和数据包读取。我已经编写了一种使用channel
和select
在CTRL+C或超时事件上停止循环的方法,但是在循环中select
会导致移动并且无法编译。
use std::time::Duration;
use tokio;
use tokio::sync::oneshot;
#[tokio::main]
async fn main() -> std::io::Result<()> {
let (src, dst) = oneshot::channel();
tokio::spawn(async {
tokio::select!{
_ = tokio::signal::ctrl_c() => (),
_ = tokio::time::sleep(Duration::from_secs(10)) => ()
}
});
let _ = connect(dst);
eprintln!("progoram finished");
Ok(())
}
async fn connect(shutdown: oneshot::Receiver<()>) -> Option<tokio::net::TcpStream> {
loop {
tokio::select! {
biased;
_ = shutdown => return None,
r = tokio::net::TcpStream::connect("127.0.0.1:80") => {
match r {
Ok(stream) => return Some(stream),
Err(err) => {
eprintln!("ERROR: {:?}", err);
tokio::time::sleep(Duration::from_secs(2)).await;
}
}
}
}
}
}
error[E0382]: use of moved value: `shutdown`
--> src/main.rs:23:17
|
20 | async fn connect(shutdown: oneshot::Receiver<()>) -> Option<tokio::net::TcpStream> {
| -------- move occurs because `shutdown` has type `tokio::sync::oneshot::Receiver<()>`, which does not implement the `Copy` trait
...
23 | _ = shutdown => return None,
| ^^^^^^^^ value moved here, in previous iteration of loop
For more information about this error, try `rustc --explain E0382`.
我做了一些更改,但无法解决错误。
_ = &shutdown => return None
→ 特质Future
未为&tokio::sync::oneshot::Receiver<()>
实现。是的,没错。_ = shutdown.into_future() => return None
,使用use std::future::IntoFuture;
→ 不稳定的库特性。
如何编写一种从外部优雅地停止这种异步重试循环的方法?
&mut shutdown
中进行选择。我在stackoverflow上找不到重复的内容,但是有人已经在这里回答了。 - Caesar&mut T
的全面实现,如此所示在这里。值得注意的是,&mut T
是不同于&T
和T
的类型,如果没有被全面实现覆盖,每个类型都需要实现一个特征。 - Henry Gomersall