异步通道上的非阻塞接收?

Posted

技术标签:

【中文标题】异步通道上的非阻塞接收?【英文标题】:Non-blocking recv on an async channel? 【发布时间】:2020-06-20 00:05:30 【问题描述】:

    我在futures::channel::mpsc::Receiver 中寻找与try_recv() 等效的内容,但找不到。有吗?有try_next(),但我不认为它符合我的要求。如果我在一个空的频道上多次调用它,我当然不希望它惊慌。

    或者,是否可以在异步代码中使用 std::sync::mpsc::channel,只要我从不在通道上进行阻塞读取(即始终使用 try_recv())?从异步函数发送给它并在同步线程中使用呢?

这里有一些关于我正在尝试做的事情的详细信息:

我正在构建一个玩家通过 websocket 连接到服务器的游戏。 websocket 端将是异步的,每个连接都会产生一个任务来循环传入消息并将它们放入通道中。该频道是我需要建议的内容 - 是否应该使用 futures::channel::mpsc::channel(并使游戏循环异步 - 但请参阅问题 1)或 std::sync::mpsc::channel(请参阅问题 2)。

游戏引擎将在单独的线程中运行,并且每帧检查一次该通道(每个玩家都有自己的通道)上的玩家输入。我想避免糟糕(或缓慢)的 websocket 客户端可能会淹没连接并减慢主游戏引擎的速度,因此我只想为每个玩家频道每帧处理一条传入消息。如果玩家自己的频道被填满,他们只会伤害自己。但是每帧检查一条传入消息需要是非阻塞的,因为它在游戏循环中运行。

那么根据上面的问题 2,以下是否可行?

异步 ​​websocket -> 同步通道 -> 同步游戏循环(反之亦然)

【问题讨论】:

futures::channel::mpsc::Receiverstream/futures... 所以就这样做 rx.await :p 我想知道我是否可以这样做。有什么好的教程/示例/文档吗?我会做一些实验。谢谢! 不多rust-lang.github.io/async-book/01_getting_started/… 当我尝试做rx.await 时,我得到the trait bound futures_channel::mpsc::Receiver<PlayerMessageExternal>: core::future::future::Future is not satisfied。这令人困惑。是不是说 futures::channel::mpsc::Receiver 不暗示 Future ?还是futures v0.3和核心库不匹配? 我建议你使用 tokio docs.rs/tokio/0.2.13/tokio/sync/mpsc/fn.channel.html 【参考方案1】:

看起来try_recv() 尚未针对 async-std 实现,尽管它似乎并不遥远(目前正在审查中)。 https://github.com/async-rs/async-std/issues/579

正如@Stargateur 所述(请参阅原始问题下的 cmets),tokio 的 mpsc 实现支持try_recv()

我已将我的代码切换为使用 tokio 0.2(以及用于 websockets 的 tokio_tungstenite),它运行良好。

【讨论】:

以上是关于异步通道上的非阻塞接收?的主要内容,如果未能解决你的问题,请参考以下文章

Java NIO - 非阻塞通道与异步通道

Java中的非阻塞异步IO

阻塞非阻塞超时(同步与异步)

Posix PIPE 上的非阻塞读取和阻塞写入

NIO实现TCP的非阻塞通信

netty为什么非阻塞