web-dev-qa-db-ja.com

TCPストリームでパイプの破損が発生するのはいつですか?

Rustでエコーサーバーを作成しようとしています。

use std::net::{TcpStream, TcpListener};
use std::io::prelude::*;

fn main() {
    let listener = TcpListener::bind("0.0.0.0:8000").unwrap();
    for stream in listener.incoming() {
        let stream = stream.unwrap();
        println!("A connection established");
        handle_connection(stream);
    }

}

fn handle_connection(mut stream: TcpStream) {
    let mut buffer = [0; 512];

    stream.read(&mut buffer).unwrap();

    println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
    stream.write(&buffer[..]).unwrap();
    stream.flush().unwrap();
}

nc localhost 8000を使用した最初のリクエストは期待どおりに機能していますが、後続のリクエストは機能していません。私は何が間違っているのですか?サーバーがクライアントからの要求を読み取る方法に問題がありますか?エラーサーバー側はありませんが。

ターミナルでデータを入力して送信しています。

$ nc localhost 8000
hi
hi
hello
# no response
# on pressing enter
Ncat: Broken pipe.
6
codeNoob

「パイプが壊れています」というメッセージは、もう一方の端が閉じられているストリームに書き込むときに発生します。この例では、handle_connectionルーチンがクライアントから単一のバッファーを読み取り、それをクライアントにコピーして戻し、ストリームを閉じます。このようにターミナルからnetcatを実行すると、ターミナルはデフォルトでラインバッファリングに設定されるため、入力した各ラインは1回の書き込みとしてサーバーに送信されます。

最初の行が送信され、サーバーによって読み取られ、エコーバックされてから、サーバーは接続を閉じます。 Netcatは2行目を取得し、それをソケットに書き込み、サーバーが接続を閉じたために「壊れたパイプ」を取得します。

サーバーに複数のメッセージを読み取らせる場合は、handle_connectionルーチンループを作成し、EOFを取得するまでストリームから読み取る必要があります。

6
Chris Dodd