Обнаружение зависания клиента в MIO
При использовании MIO (0.3.5), как я могу определить разрыв соединения?
Я попробовал следующее:
extern crate mio;
use mio::{EventLoop,Token,ReadHint};
use std::io::Read;
fn main(){
let listener = mio::tcp::TcpListener::bind("localhost:1234").unwrap();
let (stream,_) : (mio::tcp::TcpStream, _) = listener.accept().unwrap();
let mut event_loop = EventLoop::new().unwrap();
event_loop.register(&stream,Token(0)).unwrap();
println!("run...");
event_loop.run(&mut H{stream:stream}).unwrap();
}
struct H{stream : mio::tcp::TcpStream}
impl mio::Handler for H{
type Timeout = ();
type Message = ();
fn readable(&mut self, _ : &mut EventLoop<Self>, _ : Token, hint: ReadHint){
let mut buf: [u8; 500] = [0; 500];
println!("{} {}",(hint==ReadHint::data()),self.stream.read(&mut buf).unwrap());
std::thread::sleep_ms(1000);
}
}
Запустите это. Подключитесь к нему, используя что-то вроде nc localhost 1234
, Разорвите соединение с помощью Ctrl-C. Мой код будет думать, что есть новые данные (hint==ReadHint::data()
). Попытка прочитать это приведет к нулевым доступным байтам.
Не должен ли намек быть чем-то вроде ReadHint::hup()
?
1 ответ
По умолчанию при звонке register
на mio v0.3.5 стоит зарегистрироваться только для readable
Интерес, так что это единственный совет, который вы получите.
Если вы хотите, чтобы вас тоже предупредили о hup, вам нужно использовать функцию register_opt и указать Interest
а также PollOpt
в качестве параметров, ваш код становится:
extern crate mio;
use mio::{EventLoop,Token,ReadHint,PollOpt,Interest};
use std::io::Read;
fn main() {
let listener = mio::tcp::TcpListener::bind("localhost:1234").unwrap();
let (stream,_) : (mio::tcp::TcpStream, _) = listener.accept().unwrap();
let mut event_loop = EventLoop::new().unwrap();
let interest = Interest::readable() | Interest::hup();
event_loop.register_opt(&stream,Token(0), interest,PollOpt::level()).unwrap();
println!("run...");
event_loop.run(&mut H{stream:stream}).unwrap();
}
struct H{stream : mio::tcp::TcpStream}
impl mio::Handler for H {
type Timeout = ();
type Message = ();
fn readable(&mut self, event_loop : &mut EventLoop<Self>, _ : Token, hint: ReadHint){
let mut buf: [u8; 500] = [0; 500];
if hint.is_hup() {
println!("Recieved hup, exiting");
event_loop.shutdown();
return;
}
println!("{} {}",hint.is_data(),self.stream.read(&mut buf).unwrap());
std::thread::sleep_ms(1000);
}
}
Я думаю, что по умолчанию для удобства функции register
изменился в v0.4.0, чтобы быть Interest::all()
так что это не должно быть проблемой в будущем.