Search code examples
multithreadingrusttungstenite

Is is possible to share a tungstenite WebSocket connection across threads?


I would like to build a server that spawns a separate thread each for reading from and writing to a tungstenite-rs WebSocket connection, but the WebSocket object does not seem to implement clone() or try_clone() or have a split() method to be able to pass (a copy of) the connection into each thread. Am I missing something or does tungstenite just not support this approach? I know I can just use one of the async versions of tungstenite instead, but I would like to avoid that if I can.

Basically, can something like this somehow be made to work?

// Accept one connection at 127.0.0.1:8080
let mut ws_cxn = tungstenite::accept(TcpListener::bind("127.0.0.1:8080")?.accept()?.0).unwrap();

// Spawn read thread to log messages
thread::spawn(move || loop {
    if let Ok(Message::Text(msg)) = ws_cxn.read() {
        println!("Received '{}'!", msg);
    }
});

// Spawn write thread to send tick message every second
thread::spawn(move || loop {  // ERROR HERE: use of moved value: `ws_cxn`...
    ws_cxn.send(Message::Text("Tick!".to_string())).unwrap();
    thread::sleep(std::time::Duration::from_secs(1));
});

Solution

  • Check this anwser on github:

    https://github.com/snapview/tungstenite-rs/issues/171

    Shall it be explicitly documented that such arrangement is not supported by Tungstenite?

    We could include that, but I just did not want other people be confused by the full-duplex blocking connection as actually the "full-duplex blocking part" is strictly speaking not part of the library, the libraries which do allow this just implement some sort of a runtime inside of them, we don't do it in tungstenite-rs, only providing the WebSocket-related logic, so the runtime is up to the user.