0

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();
}
5
  • Please edit your post to clarify the exact output of the code you posted and the expected code. "Didn't happen" does not convey much information about what you are actually running into. Commented May 5, 2024 at 15:24
  • 2
    The read_to_string method might wait for the socket to close before returning. You may want to use some of the more primitive functions to be able to read a fixed number of bytes instead of waiting till the end of the connection. Commented May 5, 2024 at 15:29
  • @mousetail I have a doubt. In this case what will be the type of socket that gets created? I mean SOCK_STREAM or SOCK_DGRAM or SOCK_SEQPACKET like in C. Also how can I specify the socket type? Commented May 5, 2024 at 15:33
  • 1
    @Harry It's SOCK_STREAM. Commented May 5, 2024 at 15:35
  • Just as a stylistic thing/code organization thing, you should probably pull server and client apart into separate functions that return Results and do the error handling in a couple of top-level functions that do nothing but delegate to those functions and handle errors. Commented May 6, 2024 at 12:49

1 Answer 1

0

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();
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.