Asynchronous 使用异步(tokio)rust websocket在客户端之间共享可变状态

Asynchronous 使用异步(tokio)rust websocket在客户端之间共享可变状态,asynchronous,websocket,rust,rust-tokio,Asynchronous,Websocket,Rust,Rust Tokio,我正在使用Rust websocket及其基于Tokio的异步系统在Rust中编写websocket服务器。我可以很好地为客户服务,但是,我不知道如何在客户之间共享可变状态。以下是一些(部分)代码,演示了此问题: 让mut core=core::new().unwrap(); 让handle=core.handle(); 让server=server::bind(“localhost:62831”,&handle).unwrap(); 让mut state=state{ ... }; 设f=se

我正在使用Rust websocket及其基于Tokio的异步系统在Rust中编写websocket服务器。我可以很好地为客户服务,但是,我不知道如何在客户之间共享可变状态。以下是一些(部分)代码,演示了此问题:

让mut core=core::new().unwrap();
让handle=core.handle();
让server=server::bind(“localhost:62831”,&handle).unwrap();
让mut state=state{
...
};
设f=server.incoming()
.map_err(| InvalidConnection{error,…}| error)
.对于每个(|升级,|){
设f=upgrade.accept()
.然后(| s,|{
设ctx=ClientContext{
//一些其他每个客户的价值观
状态:&多个状态,
}
...
返回s.send(Message::binary(data).into())
。然后(move | s | Ok(s,ctx));//这可能是向流中插入上下文的完全错误的方法
}).然后| s,ctx |{
//这里是客户端处理代码
});
句柄。繁殖(f)
.map_err(…)
.map(…)
);
返回Ok(())
});
core.run(f.unwrap();
此代码包含以下错误:

error[E0373]:闭包可能比当前函数的寿命长,但它借用了当前函数所拥有的“**state”
-->src/main.rs:111:27
|
111 |和|(s,|)然后{
|^^^^^^^^^^^^^^^可能比借来的价值`**状态更有效`
...
114 |状态:&多个状态,
|------“**state”在这里借用
|
帮助:要强制闭包获得`**state`(以及任何其他引用变量)的所有权,请使用`move`关键字,如图所示:
|.然后(移动){
在尝试编译器的建议时,我得到以下结论:

error[E0507]:无法移出'FnMut'闭包中捕获的外部变量
-->src/main.rs:111:27
|
111 |然后|移动| | | | | | | | | | | | | | | |{
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^无法移出“FnMut”闭包中捕获的外部变量
错误:`state`的寿命不够长
-->src/main.rs:114:37
|
114 |状态:&多个状态,
|^^^^^^^活得不够长
...
122 |                 })
|-借来的价值仅在此处有效
|
=注意:借用值必须在静态生存期内有效。。。

我还尝试将状态包装到
RefCell
(在状态本身之后创建
RefCell
)但是,编译器会给出类似的移动错误,因为它试图将
RefCell
移动到创建客户端上下文的闭包中。

您与非常接近。现在需要的是包装该
RefCell
,这样您可以克隆
Rc
,而不捕获
RefCell
本身

let shared_state = Rc::new(RefCell::new(State::new())));
incoming().for_each(move |s, _| {
    let shared_state = shared_state.clone();  // Left uncaptured
    shared_state.borrow_mut().do_mutable_state_stuff(); // Could panic
});
请注意,由于您现在使用的是
Rc
RefCell
,因此可能需要继续将
ClientContext
结构转换为存储Rc>而不是
&mut State
。在某些情况下可能会继续使用
&mut State
,但您的
&mut State
结构将与e的生存期,如果您将其保持活动状态直到下一个闭包运行,则借用将死机(如果您使用
try\uu
变体,则借用将失败)

另外请记住,如果您决定在reactor中使用多个线程,您只需将
Rc
更改为,并将
RefCell
更改为,这在需要时是非常自然的转换