Unixドメインソケットサーバーは、クライアントが閉じたときにのみメッセージを出力します[重複]

Dec 04 2020

RustにUnixドメインソケットサーバーを実装しようとしています。これにより、クライアントは接続でき、クライアントはソケットを介してメッセージを送信し、サーバーはそれを印刷します。ただし、クライアントプロセスを閉じる(CTLR + C)まで、サーバーはメッセージを出力しません。問題は何でしょうか?両方のコードは次のとおりです。

サーバ:

use std::thread;
use std::os::unix::net::{UnixStream, UnixListener};
use std::io::prelude::*;
use std::io::{BufRead, BufReader};

fn main() {
    let listener = UnixListener::bind("/tmp/socket.sock").unwrap();

    for stream in listener.incoming() {
        match stream {
            Ok(mut stream) => {
                println!("Client connected!");
                thread::spawn(move ||  {
                    let mut out = String::new();
                    let mut bf = BufReader::new(stream);
                    bf.read_line(&mut out);
                    println!("{}", out);
                });
            } Err(err) => {
                println!("Connection failed!");
                break;
            }
        }
    }
    println!("Hello, world!");
}

クライアント:

use std::os::unix::net::{UnixStream, UnixListener};
use std::io::prelude::*;
use std::io::{BufWriter};

fn main() {
    let mut stream = UnixStream::connect("/tmp/socket.sock").unwrap();
    let mut bf = BufWriter::new(&stream);

    bf.write_all("Hello server".as_bytes());
    bf.flush();
    drop(bf);
}

read_to_stringメソッドでも試しましたが、クライアントが閉じるまで出力されません。誰かが問題が何であるかについて何か考えがありますか?

回答

1 DavidSchwartz Dec 04 2020 at 18:06
bf.read_line(&mut out);

読み取りコードは行を読み取ります。ただし、送信コードは行を送信しません。したがって、読み取られたコードは、要求されたとおりに行を読み取ろうとし続けます。接続が閉じられると、読み取られたコードは行を読み取ろうとすることができなくなるため、戻ります。

両側に同じプロトコルを実装する必要があります。リーダーが行末をメッセージ境界として理解している場合、ライターは、受信コードにメッセージの終了を理解させたい各ポイントに行末を配置する必要があります。

ちなみに、少なくとも経験を積むまでは、ネットワークプロトコルの上に階層化するプロトコルを文書化することをお勧めします。そうすれば、この種の間違いは避けられたでしょう。プロトコルは、メッセージが行で構成されていると言うか、メッセージが何か他のもので構成されていると言うでしょう。それにより、どちらの側が間違っていて、どちらが正しいかが明確になります。

今のように、どちらの側も間違っていても正しくもありません。彼らはただ同意しません。これらの間違いは、適切なプロトコル文書によって完全に回避されます。これらの2つのプログラムが相互に回線ベースで通信するために使用しているプロトコルですか?か否か?知るにはドキュメントが必要です。文書化することは努力する価値があります。