Search code examples
rustunix-socket

UnixStream write/read full string


I have this small example version of a problem that I have:

#[test]
fn streams() {
    use std::io::prelude::*;
    use std::net::Shutdown;
    use std::os::unix::net::UnixStream;
    use std::time::Duration;

    let (mut s1, mut s2) = UnixStream::pair().unwrap();
    s1.write_all(b"hello world").unwrap();
    // Problem is that if not calling shutdown message never arrives
    s1.shutdown(Shutdown::Write).unwrap();
    let mut response = String::new();
    s2.read_to_string(&mut response).unwrap();
    assert_eq!("hello world".to_string(), response);
}

Playground link

I need to close the connection, otherwise, the message never arrives. I think the issue is that write_all does not write EOF, so when using read_to_string hangs.

In python for example I would simply use:

socket.sendall(message.encode())
data = socket.recv(1024)

to send and get a reply.

How could I achieve the same with rust?

Thank you in advance.


Solution

  • @edwardw explanation make me realize that I should know the size of the message or close the connection. But I found another way of doing it that fitted better to what I needed, took quite interesting information from this other answer:

        let (mut s1, mut s2) = UnixStream::pair().unwrap();
        s1.write_all(b"hello world").unwrap();
        let mut buff = [0; 1024];
        let mut h = s2.take(1024);
        h.read(&mut buff);
        let mut response = String::from_utf8(buff.to_vec()).unwrap();
        let res = response.trim_end_matches(char::from(0));
        assert_eq!("hello world".to_string(), res);
    

    It may be worst for some cases, but for now it will do. Just making the stream to read up to 1024 bytes and then just trimming what I did not need from the string.