rustunix-socket

Unix domain sockets in Rust


I have written a sample code wherein I'm trying to make use of unix domain sockets to communicate between 2 threads, but not able to make that happen. After client connecting to the server, client not receiving message sent from the server, in this case Hello, I'm server.

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

fn server() {
    let listener = match UnixListener::bind("/tmp/rst.sock") {
        Ok(listener) => listener,
        Err(e) => {
            eprintln!("Couldn't bind: {e:?}");
            return;            
        }
    };

    match listener.accept() {
        Ok((mut socket, addr)) => {
            println!("Got a client: {:?} - {:?}", socket, addr);
            
            match socket.write_all(b"Hello, I'm server") {
                Ok(()) => println!("server sent"),
                Err(e) => {
                    eprintln!("server failed while writing {e:?}");
                    return;
                },
            }
            
            let mut response = String::new();
            match socket.read_to_string(&mut response) {
                Ok(length) => println!("server received {} bytes {}", length, response),
                Err(e) => {
                    eprintln!("server Couldn't read: {e:?}");
                    return;
                },
            }
        },
        Err(e) => println!("accept function failed: {:?}", e),
    }
}

fn client() {
    let mut socket = match UnixStream::connect("/tmp/rst.sock") {
        Ok(sock) => sock,
        Err(e) => {
            eprintln!("Couldn't connect: {e:?}");
            return;
        },
    };
    println!("client connected");
    
    let mut response = String::new();
    match socket.read_to_string(&mut response) {
        Ok(length) => println!("client received {} bytes {}", length, response),
        Err(e) => {
            eprintln!("client couldn't read: {e:?}");
            return;
        },
    }
    
    match socket.write_all(b"Hello, I'm client") {
        Ok(()) => println!("client sent"),
        Err(e) => {
            eprintln!("client couldn't send: {e:?}");
            return;
        },
    }
}

fn main() {
    let server_handle = std::thread::spawn(|| {
        server();
    });
    
    std::thread::sleep(std::time::Duration::from_secs(1));
    
    let client_handle = std::thread::spawn(|| {
        client();
    });
    
    let _ = server_handle.join();
    let _ = client_handle.join();
}

Solution

  • I got this thing done via uds crate which provides SEQPACKET socket types.

    use uds::{UnixSeqpacketListener, UnixSeqpacketConn};
    
    fn server() {
        let listener = match UnixSeqpacketListener::bind("/tmp/rst.sock") {
            Ok(listener) => listener,
            Err(e) => {
                eprintln!("Couldn't bind: {e:?}");
                return;            
            }
        };
    
        match listener.accept_unix_addr() {
            Ok((socket, addr)) => {
                println!("Got a client: {:?} - {:?}", socket, addr);
                
                match socket.send(b"Hello, I'm server") {
                    Ok(s) => println!("server sent {s} bytes"),
                    Err(e) => {
                        eprintln!("server failed while writing {e:?}");
                        return;
                    },
                }
                
                let mut buff = [0u8; 1024];
                match socket.recv(&mut buff) {
                    Ok(length) => println!("server received {} bytes {:?}", length, &buff[..length]),
                    Err(e) => {
                        eprintln!("server Couldn't read: {e:?}");
                        return;
                    },
                }
            },
            Err(e) => println!("accept function failed: {:?}", e),
        }
    }
    
    fn client() {
        let socket = match UnixSeqpacketConn::connect("/tmp/rst.sock") {
            Ok(sock) => sock,
            Err(e) => {
                eprintln!("Couldn't connect: {e:?}");
                return;
            },
        };
        println!("client connected");
        
        let mut buff = [0u8; 1024];
        match socket.recv(&mut buff) {
            Ok(length) => println!("client received {} bytes {:?}", length, &buff[..length]),
            Err(e) => {
                eprintln!("client couldn't read: {e:?}");
                return;
            },
        }
        
        match socket.send(b"Hello, I'm client") {
            Ok(s) => println!("client sent {s} bytes"),
            Err(e) => {
                eprintln!("client couldn't send: {e:?}");
                return;
            },
        }
    }
    
    fn main() {
        let server_handle = std::thread::spawn(|| {
            server();
        });
        
        std::thread::sleep(std::time::Duration::from_secs(1));
        
        let client_handle = std::thread::spawn(|| {
            client();
        });
        
        let _ = server_handle.join();
        let _ = client_handle.join();
    }