Strength without blocking reading with TcpStream

I have a stream that supports a list of sockets, and I would like to iterate over the list, see if there is anything to read, if so - act on it, if not - go to the next. The problem is that as soon as I run into the first node, all execution stops until something comes to a read.

I am using std::io::Read::read(&mut self, buf: &mut [u8]) -> Result<usize>

From doc

This function does not give any guarantees as to whether it blocks the data waiting for data, but if the object should block reading but cannot, it usually signals this via the return value Err.

Delving into the source, implementation of TcpStream Read

 impl Read for TcpStream { fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) } } 

What causes

 pub fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> { let fd = self.fd(); let dolock = || self.lock_nonblocking(); let doread = |nb| unsafe { let flags = if nb {c::MSG_DONTWAIT} else {0}; libc::recv(fd, buf.as_mut_ptr() as *mut libc::c_void, buf.len() as wrlen, flags) as libc::c_int }; read(fd, self.read_deadline, dolock, doread) } 

And finally, it calls read<T, L, R>(fd: sock_t, deadline: u64, mut lock: L, mut read: R)

Where can I see loops over non-blocking reads until the data is restored or an error occurs.

Is there a way to force non-blocking reads using TcpStream ?

+7
sockets tcp rust
source share
1 answer

Updated Answer

It should be noted that with Rust 1.9.0 std::net::TcpStream added functionality:

fn set_nonblocking(&self, nonblocking: bool) -> Result<()>

Original answer

It was not possible to get it using TcpStream and did not want to attach a separate lib for I / O, so I decided to set the file descriptor as non-blocking before using it and make a system call to read / write. Definitely not the safest solution, but less work than implementing the new IO library, although MIO looks great.

 extern "system" { fn read(fd: c_int, buffer: *mut c_void, count: size_t) -> ssize_t; } pub fn new(user: User, stream: TcpStream) -> Socket { // First we need to setup the socket as Non-blocking on POSIX let fd = stream.as_raw_fd(); unsafe { let ret_value = libc::fcntl(fd, libc::consts::os::posix01::F_SETFL, libc::consts::os::extra::O_NONBLOCK); // Ensure we didnt get an error code if ret_value < 0 { panic!("Unable to set fd as non-blocking") } } Socket { user: user, stream: stream } } pub fn read(&mut self) { let count = 512 as size_t; let mut buffer = [0u8; 512]; let fd = self.stream.as_raw_fd(); let mut num_read = 0 as ssize_t; unsafe { let buf_ptr = buffer.as_mut_ptr(); let void_buf_ptr: *mut c_void = mem::transmute(buf_ptr); num_read = read(fd, void_buf_ptr, count); if num_read > 0 { println!("Read: {}", num_read); } println!("test"); } } 
+6
source share

All Articles