1

我有一个 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?

4

1 回答 1

2

状态的文档io::write_all

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

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

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

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"));

如果你只是想尝试报告数据库连接失败,那就简单多了:使用Future::then代替and_then

let task = database_connection.then(|connection| match connection {
    Ok(_) => io::write_all(stream, &b"success"[..]),
    Err(_) => io::write_all(stream2, &b"error"[..]),
});
于 2018-11-18T00:30:55.747 回答