Обнаружение зависания клиента в 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() так что это не должно быть проблемой в будущем.

Другие вопросы по тегам