MIO EventLoop is not running for TcpStream

335 views Asked by At

I am a Rust beginner struggling with a problem of async IO. I've decided to use mio.

I've read some source code + tutorials but there is still some fundamental part that I do not understand. I am setting up a server with netcat -k -l 127.0.0.1 9999. Then I am running simple test with cargo (code below). I was expecting to see panic with "ready" or "tick". But it never happens and test is running forever.

extern crate mio;
use mio::*;
#[allow(unused_imports)]
use mio::tcp::TcpStream;

#[allow(dead_code)]
struct MyHandler;

impl Handler for MyHandler {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, _event_loop: &mut EventLoop<Self>, _token: Token, _event_set: EventSet) {
        panic!("ready");
    }

    fn tick(&mut self, _event_loop: &mut EventLoop<Self>) {
        panic!("tick");
    }
}

#[test]
fn mio_test1() {
    let addr = "127.0.0.1:9999".parse().unwrap();
    let mut event_loop = EventLoop::<MyHandler>::new().unwrap();
    event_loop.register(&TcpStream::connect(&addr).unwrap(), Token(0), EventSet::readable(), PollOpt::level()).unwrap();
    event_loop.run(&mut MyHandler).unwrap();
}
1

There are 1 answers

4
Vaelden On BEST ANSWER

Your problem arises from the fact that the socket you open is closed before your event loop has the chance to run.

You current code is roughly equivalent to this:

let addr = "127.0.0.1:9999".parse().unwrap();
let mut event_loop = EventLoop::<MyHandler>::new().unwrap();
{
    let sock = TcpStream::connect(&addr).unwrap();
    event_loop.register(&sock, Token(0), EventSet::readable(), PollOpt::level()).unwrap();
}   // The socket is closed here, before the event loop runs
event_loop.run(&mut MyHandler).unwrap();

So the fix is just to bind the socket to a variable so it will stay open when you call the event loop.

let addr = "127.0.0.1:9999".parse().unwrap();
let mut event_loop = EventLoop::<MyHandler>::new().unwrap();
let sock = TcpStream::connect(&addr).unwrap();
event_loop.register(&sock, Token(0), EventSet::readable(), PollOpt::level()).unwrap();
event_loop.run(&mut MyHandler).unwrap();

Your code then behaves as you expect, and panics as soon as there is something to read on the socket.