1

Rust Tokio TCP サーバーがあります。各クライアントは、次のような Tokio future チェーンによって処理されます。

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:

書き込み中にエラーが発生すると、ストリームとバッファの両方が破棄されます。

あなたのコードは、前のネットワーク メッセージが失敗したことを示すためにネットワーク メッセージを送信しようとしているように見えるため (疑わしいと思われます)、TcpStream2 番目のメッセージを送信しようとするときには、 は既になくなっています。

したがって、最も簡単な解決策は、ストリームを複製することです。

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 に答える