1

我正在使用 mio::udp::UdpSocket 接收对来自客户端的请求的响应。看起来我在触发事件上收到了部分 UDP 数据包。我不确定这是否是 mio 库中的错误。

我已经尝试过 PollOpt::level()、all()、empty()、edge() 等。我想我通常想要基于 poll() 文档的 level(),但它们都不起作用。通过添加 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),
  }
}
4

1 回答 1

1

只是为了跟进,上述逻辑中的错误是 run_once() 运行一个滴答声,而不是一个“事件”,这是一个错误的假设(尽管公平地说,该接口目前没有很好地记录)。

无论如何,这不是部分数据包问题,而是在 run_once() 逻辑运行之前未交付数据包的问题,​​在套接字上没有看到任何内容并立即返回。

在收到数据包并使用 run() 而不是 run_once() 后,我已将处理程序更改为执行 event_loop.shutdown()。

于 2015-09-17T04:27:52.580 回答