MIO EventLoop не работает для TcpStream
Я начинающий Rust, борюсь с проблемой асинхронного ввода-вывода. Я решил использовать Mio.
Я прочитал некоторые исходные коды + учебные пособия, но есть еще фундаментальная часть, которую я не понимаю. Я настраиваю сервер с netcat -k -l 127.0.0.1 9999
, Затем я запускаю простой тест с cargo
(код ниже). Я ожидал увидеть панику с "готово" или "тик". Но этого никогда не происходит, и тест работает вечно.
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 ответ
Ваша проблема возникает из-за того, что открытый вами сокет закрывается до того, как ваш цикл обработки событий сможет запустить.
Ваш текущий код примерно эквивалентен этому:
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();
Таким образом, исправление состоит в том, чтобы просто связать сокет с переменной, чтобы он оставался открытым при вызове цикла обработки событий.
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();
Ваш код ведет себя так, как вы ожидаете, и паникует, как только появляется что-то, что можно прочитать на сокете.