如何在Tokio未来链的多个分支中使用TcpStream?

时间:2018-11-17 21:55:23

标签: asynchronous tcp rust future rust-tokio

我有一个Rust Tokio TCP服务器。每个客户都由如下的Tokio未来链处理:

let stream = <TcpStream from elsewhere>;

let task = database_connection
        .and_then(connection| {
            tokio::io::write_all(stream, SomeSuccessData);
        }).map_err(|error| {
            tokio::io::write_all(stream, SomeErrorData(error));
        });

...

tokio::spawn(task);

问题是我不能在链的多个分支中使用相同的TcpStream,因为tokio::io::write_all会消耗流,即使应该按顺序使用它也是如此。至关重要的是,根据是否存在数据库错误来发送不同的数据。

我该如何克服这个问题?也许有不同的API?

1 个答案:

答案 0 :(得分:2)

io::write_all的文档指出:

  

在写入过程中发生的任何错误都会导致流和缓冲区都被破坏。

由于您的代码似乎正在尝试发送网络消息以指示先前的网络消息失败(这似乎是可疑的),因此contrib在您尝试发送第二条消息时已经消失了消息。

因此,最简单的解决方案是克隆流:

TcpStream

如果您只想尝试报告数据库连接失败,则要容易得多:使用Future::then而不是let stream2 = stream.try_clone().expect("Couldn't clone"); let task = database_connection .and_then(|_| io::write_all(stream, b"success")) .map_err(|_| io::write_all(stream2, b"error"));

and_then