Skip to content
This repository has been archived by the owner on May 15, 2018. It is now read-only.

Example of reading from a Unix socket #9

Closed
joerg-krause opened this issue Feb 23, 2017 · 5 comments
Closed

Example of reading from a Unix socket #9

joerg-krause opened this issue Feb 23, 2017 · 5 comments

Comments

@joerg-krause
Copy link

First, I am a Rust newbie...

I am trying to read data from a Unix socket, but I am failing:

extern crate futures;
extern crate tokio_core;
extern crate tokio_signal;
extern crate tokio_uds;

use std::io::Read;

use futures::{Future, Async, Poll};
use tokio_core::reactor::Core;
use tokio_uds::{UnixListener, UnixStream};

struct Echo {
    listener: UnixListener,
}

impl Future for Echo {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        loop {
            if let Async::Ready(()) = self.listener.poll_read() {
                println!("New Connection");

                let (mut stream, _) = self.listener.accept().unwrap();
                let mut buffer = Vec::new();
                stream.read_to_end(&mut buffer);
                println!("{:?}", buffer);
            }
        }
    }
}

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let listener = UnixListener::bind("/var/run/hello.sock", &handle).unwrap();

    core.run(Echo {listener: listener}).unwrap()
}

Can somebody provide an example of howto get this working, please? Thanks!

@alexcrichton
Copy link
Contributor

Perhaps tokio-core's example echo program can help? You can just replace TCP with Unix in this case

@joerg-krause
Copy link
Author

Thanks @alexcrichton ! I am trying to use it similar to the example (just without an echo):

extern crate futures;
extern crate tokio_core;
extern crate tokio_uds;

use futures::Stream;
use tokio_core::reactor::Core;
use tokio_uds::{UnixListener, UnixStream};

use std::io::Read;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let ctl = UnixListener::bind("/var/run/hello.sock", &handle).unwrap();
    let incoming = ctl.incoming();

    let done = incoming.for_each(|(mut socket, addr): (UnixStream, _)| {
        println!("New Connection: {:?}", addr);
        
        // Read the stream
        let mut hello = String::new();
        socket.read_to_string(&mut hello).unwrap();

        Ok(())
    });

    core.run(done).unwrap();
}

Unfortunately, this fails at runtime when I send some data to the socket with the error message: "Resource temporarily unavailable".

I guess I am doing it wrong, but the UnixListener is different than the TcpListener.

@alexcrichton
Copy link
Contributor

@joerg-krause yes the problem is that socket is nonblocking, so read_to_string will fail because it needs to block waiting for data. You may wish to try out the various combinators in tokio_core::io for now.

In general though all TCP examples should suffice as UDS examples

@joerg-krause
Copy link
Author

Finally, I got a working example 😄

extern crate futures;
extern crate tokio_core;
extern crate tokio_uds;

use std::fs;
use std::str;

use futures::{Future, Stream};
use tokio_core::io::read_to_end;
use tokio_core::reactor::Core;
use tokio_uds::UnixListener;

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    static PATH: &'static str = "/var/run/hello.sock";

    let listener = match UnixListener::bind(PATH, &handle) {
        Ok(m) => m,
        Err(_) => {
            fs::remove_file(PATH).unwrap();
            UnixListener::bind(PATH, &handle).unwrap()
        }
    };

    let task = listener.incoming().for_each(|(socket, _)| {
        let buf = Vec::new();
        let reader = read_to_end(socket, buf).map(|(_, _buf)| {
            println!("incoming: {:?}", str::from_utf8(&_buf).unwrap());
        }).then(|_| Ok(()));
        handle.spawn(reader);
        Ok(())
    });

    core.run(task).unwrap()
}

@alexcrichton
Copy link
Contributor

Great!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants