Sorry if the title is a tad confusing, I struggled to find the words to summarize my issue.
I have a server that read data from a serial port and forward it to client connected via websocket (using Tungstenite). The client might also send command.
When I first implemented a "blocking" version, I had two thread: one for reading new messages received by the server and one to write the serial data to the client connected. For many reason, this wasn't practical and I would like to implement and async version using tokio (and the binding for Tungstenite).
One issue is that I am not just answering to my client messages (which is what almost all the exemple in tokio-Tungstenite do), I need to actively push unrequested messages to my client.
So if I have the following code :
async fn handle_client(peer: SocketAddr, stream: TcpStream, pck_receiver: BusReader<Packet>) {
let mut own_bus = pck_receiver;
let mut ws = accept_async(stream)
.await
.expect("Failing to accept socket.");
info!("Accepted new client");
let (mut sender, mut receiver) = ws.split();
loop {
receiver.by_ref()
.try_for_each(|msg| {
info!("received msg: {}", msg);
future::ok(())
})
.await.expect("Couldnt receive?");
let b = own_bus.try_recv(); // try_recv is non-blocking
match b {
Ok(pck) => {
sender
.send(Message::Text(
serde_json::to_string(&pck).expect("could not serialize packet"),
))
.await
.expect("message could not be sent");
}
_ => (),
}
}
}
I will have the issue that the first part of the loop, where we read the received messages, will block the rest of the loop where we write the packet to the client. And because of this, I won't be able to send the packet to my client unless they first send something.
So my goal would be to isolate the "reader" part of the code in its own task that I don't wait for. But I don't know how to do this, especially since I cannot clone the WebSocketStream nor the receiver.
Since I am a huge beginner with tokio and rust futures, I feel like I am just doing things wrong and there is a much better way, but after reading a lot and trying a lot of different approach, I cannot find how to do this.
Do you have any suggestion ?