【问题标题】:How to send a stream of websocket messages using the send_all method of tokio-tungstenite如何使用 tokio-tungstenite 的 send_all 方法发送 websocket 消息流
【发布时间】:2019-09-29 10:32:21
【问题描述】:

我正在使用优秀的 rust websocket 库 tokio-tungstenite,它只是 tungstenite 的 tokio 版本。

我可以使用 connect_async 方法轻松连接到 websocket 流,在返回的 websocket 流中,我将其拆分如下:

connect_async(url).and_then(move |(ws_stream, _)| {

        let (sink, stream) = ws_stream.split();

我可以使用这样的发送消息轻松地向接收器发送一条消息:

sink.send(tungstenite::Message::Text("my message".to_string()))
.map_err(|e| ())
.wait();

这只是一个人为的例子。我的问题是我想向接收器发送消息流,我了解到最好使用 send_all 方法来完成。我的尝试是:

let my_messsages : Vec<tungstenite::Message> = vec![
tungstenite::Message::Text("message_1".to_string()), 
tungstenite::Message::Text("message_2".to_string()) ];

let send_stream: tokio_tungstenite::WebSocketStream
<tokio_tungstenite::tungstenite::Message> 
= futures::stream::iter_ok(my_messages);

sink.send_all(stream).map_err(|e| ()).wait();

但它不起作用,因为 futures::stream::iter_ok 不是构造我需要的流的正确方法,这是我卡住的地方,无法从文档中看到如何继续。

编辑:最初我没有为 send_stream 指定类型注释,它给了我这个错误:

type annotations needed for `futures::stream::iter_ok::IterOk
<std::vec::IntoIter<tungstenite::protocol::message::Message>, E>`

cannot infer type for `E`

当前错误也与发送流的类型注释有关。

【问题讨论】:

  • 一条错误消息真的很有帮助,就像 MCVE 一样。我发现了您的问题,但 实际 错误/输出而不是人工翻译会为我节省 10 分钟。
  • @SébastienRenauld 我很抱歉。感谢您的输入,我会相应地更新问题。

标签: rust


【解决方案1】:

你的问题就在这一行:

let send_stream:tokio_tungstenite::WebSocketStream<tokio_tungstenite::tungstenite::Message> 
    = futures::stream::iter_ok(my_messages);

futures::stream::iter_ok的定义如下:

pub fn iter_ok<I, E>(i: I) -> IterOk<<I as IntoIterator>::IntoIter, E> 
where
    I: IntoIterator, 

请注意,这个新流是IterOk,而不是tungstenite::WebsocketStream。通过强制类型(使用您的注释),您正在强制编译器为 IterOk 寻找 Into&lt;WebsocketStream&gt; 的实现,但没有。

因此,这失败了。

这种类型提示完全没有必要,因为 send_all 是为 impl Sink&lt;SinkItem = _, SinkError = _&gt; 定义的。

不用太意外,换行为:

let send_stream = futures::stream::iter_ok(my_messages)
  .map_err(|_:()| tungstenite::error::Error::Utf8)

应该可以完美运行,正如您的接收器所期望的 tungstenite::Message 并且这个新流具有它作为一个元素(因为它是从 Vec&lt;tungstenite::Message&gt; 构建的)。 map_err 纯粹是为了强制类型,并且在实践中永远不会被调用

【讨论】:

  • 感谢您的意见。不幸的是,这不起作用,我会解释。省略类型注释是我最初所做的,它给了我这个错误:futures::stream::iter_ok::IterOk&lt;std::vec::IntoIter&lt;tungstenite::protocol::message::Message&gt;, E&gt; 所需的类型注释无法推断E 的类型。我正在更新问题以包含此信息,因为它在这里不是很可读。感谢您的帮助。
  • @jamespearson 尝试使用 map_err() 类型强制。显然,您需要有tungstenite 可用。这样做的目的纯粹是为了解决类型。
  • 这样做会将类型注释错误转移到 map_err,说 map_err 的“_”下划线闭包参数需要一个类型。
  • @jamespearson 对此感到惊讶,但没关系。 iter_ok() 的错误类型是 (),因为它不会失败。编辑了 sn-p,[play.rust-lang.org/… playground) 似乎同意了。
  • @sebastian 谢谢你破解了它,我接受了你的回答。出于某种原因,像这样执行 send_all 会导致我所说的 websocket 服务器发送关闭响应以结束连接(可能是由于 send_all 关闭接收器)。你碰巧知道解决办法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-28
  • 1970-01-01
  • 1970-01-01
  • 2020-11-07
  • 1970-01-01
相关资源
最近更新 更多