Unix Domain Socket Server druckt nur dann eine Nachricht, wenn der Client [Duplikat] schließt.

Dec 04 2020

Ich versuche, einen Unix Domain Socket Server in Rust zu implementieren, mit dem ein Client eine Verbindung herstellen kann. Dann sendet der Client eine Nachricht über den Socket und der Server druckt sie aus. Der Server druckt die Nachricht jedoch erst, wenn ich den Client-Prozess schließe (STRG + C). Was könnte das Problem sein? Hier sind beide Codes:

Server:

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

Klient:

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

Ich habe es auch mit der Methode read_to_string versucht, aber es wird einfach nicht gedruckt, bis der Client geschlossen wird. Hat jemand eine Idee, wo das Problem liegt?

Antworten

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

Ihr Lesecode liest Zeilen . Ihr Sendecode sendet jedoch keine Zeile. Der gelesene Code versucht also weiterhin, eine Zeile so zu lesen, wie Sie es verlangt haben. Wenn die Verbindung geschlossen ist, kann der gelesene Code nicht mehr versuchen, eine Zeile zu lesen, sodass er zurückkehrt.

Sie müssen auf beiden Seiten dasselbe Protokoll implementieren. Wenn der Leser Zeilenenden als Nachrichtengrenzen versteht, muss der Schreiber an jedem Punkt, an dem der Empfangscode das Ende einer Nachricht verstehen soll, ein Zeilenende platzieren.

Übrigens ist es wirklich eine gute Idee, jedes Protokoll zu dokumentieren, das Sie über ein Netzwerkprotokoll legen, zumindest bis Sie viel mehr Erfahrung haben. Das hätte einen solchen Fehler vermieden. Entweder würde das Protokoll sagen, dass Nachrichten aus Zeilen bestehen, oder es würde sagen, dass sie aus etwas anderem bestehen, und das würde klar machen, welche Seite falsch und welche richtig ist.

So wie es jetzt ist, ist keine Seite falsch oder richtig. Sie sind sich einfach nicht einig. Diese Fehler werden durch eine ordnungsgemäße Protokolldokumentation vollständig vermieden. Ist das Protokoll, das diese beiden Programme verwenden, um zeilenbasiert miteinander zu kommunizieren? Oder nicht? Sie benötigen Dokumentation, um zu wissen. Es lohnt sich zu dokumentieren.