如何在 Rust 中保存连接 Websocket?

问题描述 投票:0回答:1

我用打字稿编写了这段代码,现在我将其迁移到 Rust,这非常简单,如果您收到一条带有“main”值的消息,它会将连接保存在 appWebClient 变量中,并且所有消息现在都发送到此应用程序WebClient。

let appWebClient: any


const createWebServer = () => {
  const wss = new WebSocket.Server({ port: 2004 }, () => {
    console.log('server started')
  })

  wss.on('connection', ws => {
    ws.on('message', data => {
      let main = JSON.parse(data)

      if (main.event == 'main') {
        appWebClient = ws
        return
      }

      let newData = main as unknown as WsBotEvents

      appWebClient.send(JSON.stringify(newData))
    })
  })

  wss.on('listening', () => {
    console.log('server listening on port 2004')
  })
}

在 Rust 代码中,我唯一能做的就是连接 websocket 服务器,

在我的 Rust 代码中,我唯一能做的就是连接 websocket 服务器,当我尝试保存连接(如果它是“main”)时,它给了我这个错误:使用移动值:

ws_sender
在循环的上一次迭代中,值移至此处

这里是完整的错误:

 error[E0382]: use of moved value: `ws_sender`
  --> src\main.rs:72:53
   |
50 | let (ws_sender, mut ws_receiver) = ws_stream.split();
   | --------- move occurs because `ws_sender` has type `SplitSink<WebSocketStream<tokio::net::TcpStream>, tokio_tungstenite::tungstenite::Message>`, which does not implement the `Copy` trait
...
53 | while let Some(Ok(Message::Text(data))) = ws_receiver.next().await {
   | -------------------------------------------------- ---------------- inside of this loop
...
72 | *main_ws = Some(ws_sender);
   | ^^^^^^^^^ value moved here, in previous iteration of loop
#[tokio::main]
async fn main() {

    tokio::spawn(ws());

    tauri::Builder::default()
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}


async fn ws() {
    let url = "127.0.0.1:2004";
    let listener = tokio::net::TcpListener::bind(url)
        .await
        .expect("Failed to bind address");

    println!("WebSocket server running on {}", url);

    let main_ws: Arc<Mutex<Option<SplitSink<WebSocketStream<TcpStream>, Message>>>> = Arc::new(Mutex::new(None));
    while let Ok((stream, _)) = listener.accept().await {
        println!("WebSocket connection accepted");

        let main_ws_clone = main_ws.clone();
        tokio::spawn(async move {
            if let Ok(ws_stream) = tokio_tungstenite::accept_async(stream).await {
                println!("New WebSocket connection established");

                let (ws_sender, mut ws_receiver) = ws_stream.split();

                // Loop para receber mensagens do cliente
                while let Some(Ok(Message::Text(data))) = ws_receiver.next().await {

                    let mut main_ws =  main_ws_clone.lock().unwrap();

                    
                    // Trate as mensagens recebidas aqui
                    let mut new_data: Value = serde_json::Value::Null;

                    match serde_json::from_str(&data) {

                        Ok(value) => {

                            new_data = value;
                            let event = new_data["event"].as_str().unwrap_or("");
                            
                            match event {
                                "main" => {

                                   
                                    *main_ws = Some(ws_sender);
                                    println!("WebSocket connection registered as main");

                                }
                                _ => {}
                            }
                        }
                        Err(_) => todo!(),
                    };
                }
            }
        });
    }
}

我已经尝试了一切,但每种选择都会给我带来不同的错误

rust websocket rust-tokio
1个回答
0
投票

问题是,当连接发送多个

"main"
事件时,
ws_sender
将被移动多次,但这是不可能的。您可以确保它仅移动一次,例如使用
Option
:

async fn ws() {
    let url = "127.0.0.1:2004";
    let listener = tokio::net::TcpListener::bind(url)
        .await
        .expect("Failed to bind address");

    println!("WebSocket server running on {}", url);

    let main_ws: Arc<Mutex<Option<SplitSink<WebSocketStream<TcpStream>, Message>>>> =
        Arc::new(Mutex::new(None));
    while let Ok((stream, _)) = listener.accept().await {
        println!("WebSocket connection accepted");

        let main_ws_clone = main_ws.clone();
        tokio::spawn(async move {
            if let Ok(ws_stream) = tokio_tungstenite::accept_async(stream).await {
                println!("New WebSocket connection established");

                let (ws_sender, mut ws_receiver) = ws_stream.split();
                let mut ws_sender = Some(ws_sender);

                // Loop para receber mensagens do cliente
                while let Some(Ok(Message::Text(data))) = ws_receiver.next().await {
                    let mut main_ws = main_ws_clone.lock().unwrap();

                    // Trate as mensagens recebidas aqui
                    let mut new_data: Value = serde_json::Value::Null;

                    match serde_json::from_str(&data) {
                        Ok(value) => {
                            new_data = value;
                            let event = new_data["event"].as_str().unwrap_or("");

                            match event {
                                "main" => {
                                    if let ws_sender @ Some(_) = ws_sender.take() {
                                        *main_ws = ws_sender;
                                    }
                                    println!("WebSocket connection registered as main");
                                }
                                _ => {}
                            }
                        }
                        Err(_) => todo!(),
                    };
                }
            }
        });
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.