Permanent Rust TcpStream

I seem to be scared with std :: io :: TcpStream. I am actually trying to open a TCP connection to another system, but the code below exactly mimics the problem.

I have a Tcp server that simply writes “Hello World” to TcpStream when opened, and then loops to open the connection.

fn main() { let listener = io::TcpListener::bind("127.0.0.1", 8080); let mut acceptor = listener.listen(); for stream in acceptor.incoming() { match stream { Err(_) => { /* connection failed */ } Ok(stream) => spawn(proc() { handle(stream); }) } } drop(acceptor); } fn handle(mut stream: io::TcpStream) { stream.write(b"Hello Connection"); loop {} } 

All the client does is try to read one byte from the connection and print it.

 fn main() { let mut socket = io::TcpStream::connect("127.0.0.1", 8080).unwrap(); loop { match socket.read_byte() { Ok(i) => print!("{}", i), Err(e) => { println!("Error: {}", e); break } } } } 

Now the problem is that my client remains blocked while reading until I kill the server or close the TCP connection. This is not what I want, I need to open a TCP connection for a very long time and send messages back and forth between the client and server. What i don't understand here? I have the same problem with the real system that I am talking to - I will only unlock as soon as I kill the connection.

+6
source share
1 answer

Unfortunately, Rust currently does not have the capability for asynchronous I / O. There are some attempts to rectify the situation, but they are still far from complete. That is, there is a desire to make truly asynchronous input-output possible (offers include the choice of sources and input-output channels at the same time, which will allow you to run tasks that are blocked inside the input-output through an event through although it is not clear how it should be implemented on all supported platforms), but much remains to be done, and now, as far as I know, there is nothing useful.

You can emulate this to some extent using timeouts. This is far from the best solution, but it works. It might look like this (simplified example from my code base):

 let mut socket = UdpSocket::bind(address).unwrap(); let mut buf = [0u8, ..MAX_BUF_LEN]; loop { socket.set_read_timeout(Some(5000)); match socket.recv_from(buf) { Ok((amt, src)) => { /* handle successful read */ } Err(ref e) if e.kind == TimedOut => {} // continue Err(e) => fail!("error receiving data: {}", e) // bail out } // do other work, check exit flags, for example } 

Here recv_from will return an IoError with kind set to TimedOut if there is no data available on the socket for 5 seconds inside the recv_from call. You need to reset the waiting time before each iteration of the loop, since it looks more like a “deadline” than a timeout — when it expires, all calls will fail with a timeout error.

This is definitely not how it should be done, but Rust currently provides nothing better. At least he does his job.

Update

An attempt is being made to create an asynchronous event loop and network I / O on it. It is called mio . This could probably be a good temporary (or even permanent, who knows) solution for asynchronous I / O.

+7
source

Source: https://habr.com/ru/post/974730/


All Articles