我是Rust的新手,我正在实现一个简单的客户端服务器应用程序。我设法让应用程序从std::sync::TcpStream库工作。现在我希望服务器能够使用时雄库异步地接受请求。应用程序的操作基于两种类型的客户端,写入器和读取器。写入器将通过tcp流写入服务器,读取器将阅读服务器上的内容。为了在服务器上建立内部连接,我使用时雄通道。
当我试图通过参数将我创建的通道的发送者和接收者传递给处理流的函数时,我遇到的问题是相关的。
这里是代码。我想我真的不明白变量引用在rust中是如何工作的。
use tokio::net::TcpListener;
use tokio::net::TcpStream;
use tokio::sync::mpsc;
use tokio::sync::mpsc::{Sender, Receiver};
use std::error::Error;
async fn handle_connection(mut stream: TcpStream, sender: &Sender<[u8; 128]>, receiver: &Receiver<[u8; 128]>) -> Result<(), Box<dyn Error>> {
//do something...
}
pub async fn create_listener(addr: String) -> Result<(), Box<dyn Error>> {
let listener = TcpListener::bind(&addr).await?;
let (sender, receiver) = mpsc::channel(10);
loop {
let (mut stream, _) = listener.accept().await?;
tokio::spawn(async move {
handle_connection(stream, &sender, &receiver);
});
}
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
create_listener(String::from("127.0.0.1:8000")).await?;
Ok(())
}
字符串
返回的错误如下:
error[E0382]: use of moved value: `sender`
--> src/server-t.rs:49:33
|
44 | let (sender, receiver) = mpsc::channel(10);
| ------ move occurs because `sender` has type `tokio::sync::mpsc::Sender<[u8; 128]>`, which does not implement the `Copy` trait
...
49 | tokio::spawn(async move {
| _________________________________^
50 | | handle_connection(stream, &sender, &receiver);
| | ------ use occurs due to use in generator
51 | | });
| |_________^ value moved here, in previous iteration of loop
error[E0382]: use of moved value: `receiver`
--> src/server-t.rs:49:33
|
44 | let (sender, receiver) = mpsc::channel(10);
| -------- move occurs because `receiver` has type `tokio::sync::mpsc::Receiver<[u8; 128]>`, which does not implement the `Copy` trait
...
49 | tokio::spawn(async move {
| _________________________________^
50 | | handle_connection(stream, &sender, &receiver);
| | -------- use occurs due to use in generator
51 | | });
| |_________^ value moved here, in previous iteration of loop
型
你能解释一下为什么会这样吗?怎么解决?
1条答案
按热度按时间vshtjzan1#
当您在
async move
块中捕获某个变量时,它将被移动到块中。因此,sender
和receiver
被移动到async块中,并且不能在循环的下一次迭代中重用。经典的解决方法是将它们 Package 在
Arc
中,以便共享所有权。这将适用于发送方,因为Sender::send()
需要&self
,所以即使使用Arc
也可以发送。但是Receiver::recv()
需要&mut self
(因为这是一个多生产者单一消费者通道),所以您无法从&Receiver
或Arc<Receiver>
接收。最简单的解决方法是使用
broadcast
通道,这是一个多生产者多消费者通道。这将是效率较低,虽然,也有一个语义上的差异:对于广播信道,如果接收机在发送之后注册,则它将不接收消息,而对于MPSC信道,它将接收消息。另一种选择是用
Arc<Mutex<Option>>>
Package 接收器,并为读取器 Package.lock().unwrap().take().expect("two readers")
。