在BusReader和warp WebSocket接收器之间转发消息是否会使缓冲区未刷新?

在BusReader和warp WebSocket接收器之间转发消息是否会使缓冲区未刷新?,websocket,rust,rust-warp,Websocket,Rust,Rust Warp,我正在尝试创建一个websocket服务器(以及HTTP,因此使用warp),它通过websocket将消息从一个源(MQTT订阅)转发到多个客户端。除了客户端在第二条消息被广播之前不接收第一条websocket消息之外,这似乎工作得很好;然后总是留下一条信息,直到最后再也没有收到最后一条信息。在我看来,问题似乎在于ws\u connected函数中的发送缓冲区从未完全刷新 我使用将转换为流,然后将消息映射到WebSocket接收器所需的Ok(Message)类型。官方的warp websock

我正在尝试创建一个websocket服务器(以及HTTP,因此使用warp),它通过websocket将消息从一个源(MQTT订阅)转发到多个客户端。除了客户端在第二条消息被广播之前不接收第一条websocket消息之外,这似乎工作得很好;然后总是留下一条信息,直到最后再也没有收到最后一条信息。在我看来,问题似乎在于
ws\u connected
函数中的发送缓冲区从未完全刷新

我使用将转换为流,然后将消息映射到WebSocket接收器所需的
Ok(Message)
类型。官方的warp websocket聊天示例使用类似的结构在流之间进行转发:

在这个简化的示例中,服务器通过总线广播值0-9。websocket客户端(以及Firefox中的JS websocket客户端)接收消息0-8(尽管总是在broacast和服务器的stdout后面),但9永远不会到达。然而,
async_bus_print
函数会及时接收所有值,这证明消息至少通过总线没有问题

以下是服务器进程的输出:

async bus_print started
0
async bus: "0"
1
async bus: "1"
2
async bus: "2"
3
async bus: "3"
4
async bus: "4"
5
async bus: "5"
6
async bus: "6"
7
async bus: "7"
8
async bus: "8"
9
async bus: "9"
有关守则:

use std::{sync::{Arc, RwLock}, thread};

use bus::{Bus, BusReader};
use futures::StreamExt;
use warp::ws::{Message, WebSocket};
use warp::Filter;

async fn ws_connected(ws: WebSocket, rx: BusReader<String>) {
    let (ws_tx, _ws_rx) = ws.split();

    thread::spawn(|| {
        futures::executor::block_on(async move {
            if let Err(e) = futures::stream::iter(rx.into_iter())
                .map(|ws_msg| Ok(Message::text(ws_msg)))
                .forward(ws_tx)
                .await
            {
                eprintln!("Goodbye, websocket user: {}", e);
            }
        });
    });
}

async fn async_bus_print(mut rx: BusReader<String>) {
    println!("async bus_print started");
    thread::spawn(||
        futures::executor::block_on(async move {
            while let Some(msg) = futures::stream::iter(rx.iter()).next().await {
                println!("async bus: {:#?}", msg);
            }
        })
    );
}

async fn bus_tx(tx: Arc<RwLock<Bus<String>>>) {
    for i in 0..10u8 {
        tx.write().unwrap().broadcast(format!("{}", i));
        println!("{}", i);
        tokio::time::delay_for(std::time::Duration::from_secs(1)).await;
    }
}

#[tokio::main]
async fn main() {
    let bus = Arc::new(RwLock::new(Bus::new(20)));
    let bus2 = Arc::clone(&bus);
    let rx = warp::any().map(move || bus2.write().unwrap().add_rx());
    let rx2 = bus.write().unwrap().add_rx();

    let ws = warp::path("ws")
        .and(warp::ws())
        .and(rx)
        .map(|ws: warp::ws::Ws, rx| ws.on_upgrade(move |socket| ws_connected(socket, rx)));

    futures::join!(
        async_bus_print(rx2),
        bus_tx(bus),
        warp::serve(ws).run(([127, 0, 0, 1], 3030)),
    );
}
使用std:{sync::{Arc,RwLock},thread};
使用总线:{bus,BusReader};
使用futures::StreamText;
使用warp::ws::{Message,WebSocket};
使用warp::Filter;
异步fn ws_连接(ws:WebSocket,rx:BusReader){
let(ws_tx,_ws_rx)=ws.split();
线程::spawn(| |{
futures::executor::block_on(异步移动){
如果让错误(e)=未来::流::iter(rx.into_iter())
.map(| ws_msg | Ok(Message::text(ws_msg)))
.转发(ws_tx)
.等待
{
eprintln!(“再见,websocket用户:{}”,e);
}
});
});
}
异步fn异步总线打印(mut rx:BusReader){
println!(“异步总线_打印已启动”);
线程::繁殖(||
futures::executor::block_on(异步移动){
而让一些(msg)=未来::流::iter(rx.iter()).next()等待{
println!(“异步总线:{:#?}”,msg);
}
})
);
}
异步fn总线_tx(tx:Arc){
对于0..10u8中的i{
tx.write().unwrap().broadcast(格式!(“{}”,i));
println!(“{}”,i);
tokio::time::delay_for(std::time::Duration::from_secs(1))。等待;
}
}
#[tokio::main]
异步fn main(){
let bus=Arc::new(RwLock::new(bus::new(20));
让bus2=Arc::clone(&bus);
让rx=warp::any().map(移动| | bus2.write().unwrap().add|rx());
设rx2=bus.write().unwrap().add_rx();
让ws=warp::path(“ws”)
.和(warp::ws())
.及(rx)
.map(|ws:warp::ws::ws,rx | ws.on|u升级(移动|套接字| ws|u连接(套接字,rx));
未来:加入(
异步总线打印(rx2),
总线(总线),
warp::serve(ws).run([127,0,0,1],3030)),
);
}
我如何追踪并消除这个“缓冲”问题


希望我解释得足够好。如果我能提供更多信息,请告诉我。感谢您的帮助。

虽然我仍然无法找出未刷新数据的根本原因,但多亏了reddit上一些有帮助的人,我有了一些更好的替代解决方案

如果不首先拆分WebSocket,它似乎工作得很好:

async fn ws_connected(ws: WebSocket, rx: BusReader<String>) {
    thread::spawn(|| {
        futures::executor::block_on(async move {
            if let Err(e) = futures::stream::iter(rx.into_iter())
                .map(|ws_msg| Ok(Message::text(ws_msg)))
                .forward(ws)
                .await
            {
                eprintln!("Goodbye, websocket user: {}", e);
            }
        });
    });
}
最终,我认为东京的
广播
频道比
总线
更适合我的异步多生产者、多消费者频道通信需求:

use futures::StreamExt;
use tokio::sync::broadcast;
use warp::ws::{Message, WebSocket};
use warp::Filter;

async fn ws_connected(ws: WebSocket, recv: broadcast::Receiver<String>) {
    let (ws_tx, _ws_rx) = ws.split();

    recv.map(|s| Ok(Message::text(s.unwrap())))
        .forward(ws_tx)
        .await
        .unwrap();
}

async fn async_bus_print(mut recv: broadcast::Receiver<String>) {
    println!("async bus_print started");
    while let Some(msg) = recv.next().await {
        println!("async bus: {:#?}", msg.unwrap());
    }
}

async fn bus_tx(tx: broadcast::Sender<String>) {
    for i in 0..10u8 {
        tx.send(format!("{}", i)).unwrap();
        println!("{}", i);
        tokio::time::delay_for(std::time::Duration::from_secs(1)).await;
    }
}

#[tokio::main]
async fn main() {
    let (send, recv) = broadcast::channel::<String>(32);
    let send2 = send.clone();
    let rx = warp::any().map(move || send2.subscribe());

    let ws = warp::path("ws")
        .and(warp::ws())
        .and(rx)
        .map(|ws: warp::ws::Ws, recv| ws.on_upgrade(move |socket| ws_connected(socket, recv)));

    let (abp, tx, warp) = futures::join!(
        tokio::spawn(async_bus_print(recv)),
        tokio::spawn(bus_tx(send)),
        tokio::spawn(warp::serve(ws).run(([127, 0, 0, 1], 3030))),
    );

    abp.unwrap();
    tx.unwrap();
    warp.unwrap();
}
使用futures::StreamText;
使用东京::同步::广播;
使用warp::ws::{Message,WebSocket};
使用warp::Filter;
异步fn ws_已连接(ws:WebSocket,recv:broadcast::Receiver){
let(ws_tx,_ws_rx)=ws.split();
recv.map(| s | Ok(Message::text(s.unwrap()))
.转发(ws_tx)
.等待
.unwrap();
}
异步fn异步总线打印(mut recv:broadcast::Receiver){
println!(“异步总线_打印已启动”);
而让一些(msg)=recv.next()等待{
println!(“异步总线:{:#?}”,msg.unwrap();
}
}
异步fn总线_tx(tx:broadcast::Sender){
对于0..10u8中的i{
tx.send(format!(“{}”,i)).unwrap();
println!(“{}”,i);
tokio::time::delay_for(std::time::Duration::from_secs(1))。等待;
}
}
#[tokio::main]
异步fn main(){
let(send,recv)=广播::频道::(32);
让send2=send.clone();
让rx=warp::any().map(move | | send2.subscribe());
让ws=warp::path(“ws”)
.和(warp::ws())
.及(rx)
.map(| ws:warp::ws::ws,recv | ws.on|u升级(移动|套接字| ws|u连接(套接字,recv)));
让(abp,tx,warp)=未来::加入(
tokio::spawn(异步总线打印(recv)),
东京:产卵(总线发送),
tokio::spawn(warp::service(ws).run([127,0,0,1,3030)),
);
abp.unwrap();
tx.展开();
扭曲。展开();
}
use futures::StreamExt;
use tokio::sync::broadcast;
use warp::ws::{Message, WebSocket};
use warp::Filter;

async fn ws_connected(ws: WebSocket, recv: broadcast::Receiver<String>) {
    let (ws_tx, _ws_rx) = ws.split();

    recv.map(|s| Ok(Message::text(s.unwrap())))
        .forward(ws_tx)
        .await
        .unwrap();
}

async fn async_bus_print(mut recv: broadcast::Receiver<String>) {
    println!("async bus_print started");
    while let Some(msg) = recv.next().await {
        println!("async bus: {:#?}", msg.unwrap());
    }
}

async fn bus_tx(tx: broadcast::Sender<String>) {
    for i in 0..10u8 {
        tx.send(format!("{}", i)).unwrap();
        println!("{}", i);
        tokio::time::delay_for(std::time::Duration::from_secs(1)).await;
    }
}

#[tokio::main]
async fn main() {
    let (send, recv) = broadcast::channel::<String>(32);
    let send2 = send.clone();
    let rx = warp::any().map(move || send2.subscribe());

    let ws = warp::path("ws")
        .and(warp::ws())
        .and(rx)
        .map(|ws: warp::ws::Ws, recv| ws.on_upgrade(move |socket| ws_connected(socket, recv)));

    let (abp, tx, warp) = futures::join!(
        tokio::spawn(async_bus_print(recv)),
        tokio::spawn(bus_tx(send)),
        tokio::spawn(warp::serve(ws).run(([127, 0, 0, 1], 3030))),
    );

    abp.unwrap();
    tx.unwrap();
    warp.unwrap();
}