gpt4 book ai didi

rust - 如何使用 Rust 与 Actix web 和 WebSockets 发送服务器事件?

转载 作者:行者123 更新时间:2023-11-29 08:19:44 29 4
gpt4 key购买 nike

我将 Rust 与 Actix web 结合使用,并希望将 WebSockets 用于服务器事件,主要是发送到客户端的状态消息。我遵循了基本结构,

struct StatusWS {}

impl Actor for StatusWS {
type Context = ws::WebsocketContext<Self>;

fn started(&mut self, ctx: &mut Self::Context) {
// How to keep track of ctx???
}
}

当客户端连接时,started() 被调用,我可以使用 ctx.text() 等从那里发送消息。但是,我需要跟踪上下文以便稍后发送消息。我怎么做?它作为引用传入,因此借用检查器不会让我用它做太多事情。

最佳答案

这对我来说是深水区,但我认为你需要impl Handler 用于 StatusWS。然后您可以使用Addr当您 .start() 您的 Actor 向其发送消息时,您将获得作为返回值。然后,您将进入 Handlerhandle 方法,该方法可以访问 ctx 并且您可以发送您的 ws 消息。

我自己正在学习 Rust 和 Actix,所以这可能不是你实际做的方式。让我知道进展如何。

[编辑]我意识到我的答案有点黯淡,所以我举了一个可能对其他人有用的例子。

use actix::prelude::*;
use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer};
use actix_web_actors::ws;
use std::time::Duration;

fn ws_index(
r: HttpRequest,
stream: web::Payload,
data: web::Data<Addr<ServerMonitor>>,
) -> Result<HttpResponse, Error> {
let (addr, res) = ws::start_with_addr(MyWebSocket {}, &r, stream)?;

data.get_ref().do_send(RegisterWSClient { addr: addr });

Ok(res)
}

struct MyWebSocket {}

impl Actor for MyWebSocket {
type Context = ws::WebsocketContext<Self>;
}

impl StreamHandler<ws::Message, ws::ProtocolError> for MyWebSocket {
fn handle(&mut self, msg: ws::Message, ctx: &mut Self::Context) {
println!("WS: {:?}", msg);
match msg {
ws::Message::Ping(msg) => {
ctx.pong(&msg);
}
ws::Message::Pong(_) => {}
ws::Message::Text(text) => ctx.text(text),
ws::Message::Binary(bin) => ctx.binary(bin),
ws::Message::Close(_) => {
ctx.stop();
}
ws::Message::Nop => (),
}
}
}

impl Handler<ServerEvent> for MyWebSocket {
type Result = ();

fn handle(&mut self, msg: ServerEvent, ctx: &mut Self::Context) {
ctx.text(msg.event);
}
}

#[derive(Message)]
struct RegisterWSClient {
addr: Addr<MyWebSocket>,
}

#[derive(Message)]
struct ServerEvent {
event: String,
}

struct ServerMonitor {
listeners: Vec<Addr<MyWebSocket>>,
}

impl Actor for ServerMonitor {
type Context = Context<Self>;

fn started(&mut self, ctx: &mut Self::Context) {
ctx.run_interval(Duration::from_secs(5), |act, _| {
for l in &act.listeners {
l.do_send(ServerEvent{ event: String::from("Event:") });
}
});
}
}

impl Handler<RegisterWSClient> for ServerMonitor {
type Result = ();

fn handle(&mut self, msg: RegisterWSClient, _: &mut Context<Self>) {
self.listeners.push(msg.addr);
}
}

fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix_server=info,actix_web=info");
env_logger::init();

let sys = actix_rt::System::new("example");

let srvmon = ServerMonitor { listeners: vec![] }.start();

HttpServer::new(move || {
App::new()
.data(srvmon.clone())
.wrap(middleware::Logger::default())
.service(web::resource("/ws/").route(web::get().to(ws_index)))
})
.bind("127.0.0.1:8080")?
.start();

sys.run()
}

关于rust - 如何使用 Rust 与 Actix web 和 WebSockets 发送服务器事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58424473/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com