向具有多个WebSocket引用的客户端发送消息
我在这里的问题是在使用actix web时遇到的 不幸的是,如果没有一个有点繁重的代码示例,我无法解释这一点,所以让我从这个开始向具有多个WebSocket引用的客户端发送消息,websocket,rust,rust-tokio,rust-actix,actix-web,Websocket,Rust,Rust Tokio,Rust Actix,Actix Web,我在这里的问题是在使用actix web时遇到的 不幸的是,如果没有一个有点繁重的代码示例,我无法解释这一点,所以让我从这个开始 struct MyWs { game: Arc<RwLock<Game>>, } impl Actor for MyWs { type Context = ws::WebsocketContext<Self>; } impl StreamHandler<Result<ws::Message, ws::
struct MyWs {
game: Arc<RwLock<Game>>,
}
impl Actor for MyWs {
type Context = ws::WebsocketContext<Self>;
}
impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for MyWs {
fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
match msg {
Ok(ws::Message::Text(text)) => {
debug!("Echoing text with {:?}", text);
self.game.write().unwrap().some_method();
ctx.text(text)
},
_ => (),
}
}
}
struct Game {
websockets: Vec<Arc<RwLock<MyWs>>>,
}
impl Game {
pub fn new() -> GameWrapper {
GameWrapper {
websockets: vec![],
}
}
pub fn add_websocket(&mut self, my_ws: Arc<RwLock<MyWs>>) {
self.websockets.push(my_ws);
}
pub fn some_method(&mut self) {
// Do something to influence internal state.
self.push_state();
}
pub fn push_state(&self) {
for w in self.websockets {
// I'm not sure about this part, idk how to access the
// WebsocketContext with which I can send stuff back to the client.
let game_state = get_game_state_or_something();
w.write().unwrap().ctx.text(self.game_state);
}
}
}
struct GameWrapper {
pub game: Arc<RwLock<Game>>,
}
impl GameWrapper {
pub fn new(game: Arc<RwLock<Game>>) -> GameWrapper {
GameWrapper { game }
}
}
#[actix_rt::main]
async fn main() -> std::io::Result<()> {
let game = Arc::new(RwLock::new(Game::new()));
let game_wrapper = RwLock::new(GameWrapper::new(game.clone()));
let game_wrapper_data = web::Data::new(game_wrapper);
HttpServer::new(move || {
App::new()
.app_data(game_wrapper_data.clone())
.route("/play_game", web::get().to(play_game))
})
.bind(ip_port)?
.run()
.await
}
pub async fn play_game(
req: HttpRequest,
stream: web::Payload,
game_wrapper: web::Data<GameWrapper>,
) -> impl Responder {
let my_ws = MyWs { game: game_wrapper.game.clone() };
let my_ws = Arc::new(RwLock::new(my_ws));
let mut game = game_wrapper.game.write().unwrap();
game.add_websocket(my_ws);
let resp = ws::start(my_ws, &req, stream); // This is the problem.
let resp = match resp {
Ok(resp) => resp,
Err(e) => return HttpResponse::from_error(e),
};
debug!("Successfully upgraded to websocket");
resp
}
struct MyWs{
游戏:Arc,
}
MyWs的impl-Actor{
类型Context=ws::WebsocketContext;
}
MyWs的impl StreamHandler{
fn句柄(&mut self,msg:Result,ctx:&mut self::Context){
配味精{
确定(ws::Message::Text(Text))=>{
调试!(“用{:?}回显文本”,文本);
self.game.write().unwrap().some_方法();
ctx.text(text)
},
_ => (),
}
}
}
结构游戏{
WebSocket:Vec
好的,所以我的困境的解决方案是改变我试图解决这个问题的方式,这并不奇怪。我真正需要的不是对websocket的多个引用,而是对持有websocket的每个参与者的引用。我想这就是你要做的,因为Actix是一个参与者框架
这意味着代码应该如下所示:
impl Game {
...
pub fn register_actor(&mut self, actor: Addr<MyWs>) {
self.actors.push(actor);
}
}
pub async fn play_game(
req: HttpRequest,
stream: web::Payload,
game_wrapper: web::Data<GameWrapper>,
) -> impl Responder {
let my_ws = MyWs { game: game_wrapper.game.clone() };
let my_ws = Arc::new(RwLock::new(my_ws));
let mut game = game_wrapper.game.write().unwrap();
let res = ws::start_with_addr(my_ws, &req, stream);
let (addr, resp) = match res {
Ok(res) => res,
Err(e) => return HttpResponse::from_error(e),
};
game_manager.register_actor(handle, addr);
debug!("Successfully upgraded to websocket");
resp
}
impl游戏{
...
发布fn寄存器\u参与者(&mut self,参与者:Addr){
self.actors.push(actor);
}
}
酒吧异步fn玩游戏(
请求:HttpRequest,
流:web::Payload,
游戏包装器:web::Data,
)->impl应答器{
让my_ws=MyWs{game:game_wrapper.game.clone()};
让my_ws=Arc::new(RwLock::new(my_ws));
让mut game=game_wrapper.game.write().unwrap();
让res=ws::用_addr(我的_-ws,&req,流)启动_;
let(addr,resp)=匹配res{
Ok(res)=>res,
Err(e)=>返回HttpResponse::from_error(e),
};
游戏经理。注册演员(手柄,地址);
调试!(“已成功升级到websocket”);
响应
}
然后,您可以通过Addr
向参与者发送消息
我将把这个问题留一段时间,以防其他人对如何更好地完成整个任务有想法。我试图突破ws::start
,但我遇到了一个类似的问题:。您是如何通过Addr发送Websocket消息的?因为Addr是一个actix构造,Addr::send()获取一条actix::Message,而这条actix::Message没有实现。。。