Unix Domain Socket Server solo imprime el mensaje cuando el cliente cierra [duplicado]

Dec 04 2020

Estoy tratando de implementar un servidor de socket de dominio Unix en Rust, que permite que un cliente se conecte, luego el cliente envía un mensaje a través del socket y el servidor lo imprime. Sin embargo, el servidor no imprime el mensaje hasta que cierre (CTLR + C) el proceso del cliente. ¿Cuál podría ser el problema? Aquí están los dos códigos:

Servidor:

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

Cliente:

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

También lo intenté con el método read_to_string, pero simplemente no se imprime hasta que el cliente se cierra. ¿Alguien tiene alguna idea de cuál es el problema?

Respuestas

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

Su código leído lee líneas . Pero su código de envío no envía una línea. Entonces, el código de lectura continúa intentando leer una línea como usted le pidió que lo hiciera. Cuando se cierra la conexión, el código leído ya no puede intentar leer una línea, por lo que regresa.

Tienes que implementar el mismo protocolo en ambos lados. Si el lector entiende que los finales de línea son límites del mensaje, entonces el escritor debe colocar un final de línea en cada punto en el que desea que el código de recepción entienda el final de un mensaje.

Por cierto, es realmente una buena idea documentar cualquier protocolo que vaya a colocar encima de un protocolo de red, al menos hasta que tenga mucha más experiencia. Eso habría evitado este tipo de error. O el protocolo diría que los mensajes constan de líneas o diría que constan de otra cosa, y eso dejaría claro qué lado está mal y cuál es el correcto.

Como está ahora, ninguno de los lados está equivocado o correcto. Ellos simplemente no están de acuerdo. Estos errores se evitan por completo mediante la documentación del protocolo adecuada. ¿El protocolo que utilizan estos dos programas para comunicarse entre sí está basado en líneas? ¿O no? Necesita documentación para saberlo. Vale la pena el esfuerzo de documentar.