Получение частичных пакетов UDP от mio::udp::UdpSocket.recv

Я использую mio::udp::UdpSocket, чтобы получить ответ на запрос от клиента. Похоже, я получаю частичные UDP-пакеты при сработавшем событии. Я не уверен, является ли это ошибкой в ​​библиотеке mio или нет.

Я пробовал PollOpt::level(), all(), empty(), edge() и т. Д. Я думаю, что я обычно хочу level () на основе документов poll(), но ни один из них не работает. Добавляя время ожидания 20 мс, я получаю полные пакеты.

В качестве ссылки, при использовании блокировки std::net::UdpSocket я не вижу проблем. Честно говоря, если бы std::net::SocketOpts был стабильным, я бы просто использовал это. Цель использования mio - получить тайм-аут в сокете, похоже, что net2 заменит std:: net, но даже у net2 нет тайм-аута в recv.

Вот код для цикла событий:

sleep_ms(20);

let mut event_loop: EventLoop<Response> = try!(EventLoop::new());

if event_loop.timeout_ms((), 5000).is_err() { return Err(ClientError::TimerError) };
try!(event_loop.register_opt(&self.socket, RESPONSE, EventSet::readable(), PollOpt::all()));

let mut response: Response = Response::new(&self.socket);

try!(event_loop.run_once(&mut response));

Вот код для обработчика:

fn ready(&mut self, _: &mut EventLoop<Self>, token: Token, events: EventSet) {
  match token {
    RESPONSE => {
      if !events.is_readable() {
        debug!("got woken up, but not readable: {:?}", token);
        return
      }

      let recv_result = self.socket.recv_from(&mut self.buf);
      if recv_result.is_err() {
        // debug b/c we're returning the error explicitly
        debug!("could not recv_from on {:?}: {:?}", self.socket, recv_result);
        self.error = Some(recv_result.unwrap_err().into());
        return
      }

      if recv_result.as_ref().unwrap().is_none() {
        // debug b/c we're returning the error explicitly
        debug!("no return address on recv_from: {:?}", self.socket);
        self.error = Some(ClientError::NoAddress);
        return
      }

      let addr = Some(recv_result.unwrap().unwrap());
      debug!("bytes: {:?} from: {:?}", self.buf.len(), addr);
    },
    _ => error!("unrecognized token: {:?}", token),
  }
}

1 ответ

Просто для продолжения, ошибка в вышеприведенной логике заключается в том, что run_once() работает для галочки, а не для одного "события", что было неверным предположением (хотя, чтобы быть справедливым, интерфейс в настоящее время плохо документирован).

В любом случае, это не частичная проблема с пакетом, это проблема того, что пакет не был доставлен до запуска логики run_once(), ничего не увидел в сокете и сразу же вернулся.

Я изменил свой обработчик так, чтобы он делал event_loop.shutdown() после получения пакета и использования run () вместо run_once().

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