4

我已经通读了 boost:asio 文档(在异步客户端上看起来很安静),并在此处查看,但似乎无法在此处找到树木的森林。

我有一个模拟,它的主循环如下所示:

for(;;)
{
  a = do_stuff1();
  do_stuff2(a);
}

很容易。

我想做的是修改它,以便我拥有:

for(;;)
{
  a = do_stuff1();
  check_for_new_received_udp_data(&b);
  modify_a_with_data_from_b(a,b);
  do_stuff2(a);
}

我有以下要求:

  1. 我不能因为没有积极倾听而丢失数据。IE 我不想丢失数据包,因为在服务器发送数据包时我在 do_stuff2() 而不是 check_for_new_received_udp_data() 中。
  2. 我不能让 check_for_new_received_udp_data() 块超过大约 2 毫秒,因为主 for 循环需要以 60Hz 执行。
  3. 服务器将在其他地方运行,并且有一个完全不稳定的时间表。有时会没有数据,有时我可能会重复收到相同的数据包。

我玩过异步 UDP,但这需要调用 io_service.run(),它会无限期地阻塞,所以这对我没有帮助。

我考虑过超时阻塞套接字读取,但似乎你必须作弊并退出 boost 调用才能做到这一点,所以这是一个非首发。

答案会涉及线程吗?无论哪种方式,有人可以指出一个有点相似的例子吗?当然,这在以前已经做过了。

4

2 回答 2

3

为避免阻塞,io_service::run()您可以使用io_service::poll_one()

关于丢失 UDP 数据包,我认为你不走运。UDP 不保证传送,如果流量很大,网络的任何部分都可能决定丢弃 UDP 数据包。如果您需要确保交付,您需要实现某种流控制或仅使用 TCP。

于 2013-03-24T21:17:12.487 回答
3

我认为您的问题是您仍在同步思考。你需要异步思考。

  1. UDP 套接字上的异步读取 - 数据到达时将调用处理程序。
  2. 在该处理程序中对传入数据进行处理。请记住,在处理过程中,如果您有一个线程,则不会调度任何其他内容。这完全没问题(UDP 消息仍将在网络堆栈中排队......)。
  3. 因此,您可能正在启动其他异步操作。

如果您需要并行进行本质上不相关或离线的工作,这将涉及线程。创建一个调用 io_service.run() 的线程。

如果您需要在异步框架中进行定期工作,请使用timers

在您的特定示例中,我们可以重新排列这样的内容(伪代码):

read_handler( ... )
{
   modify_a_with_data_from_b(a,b);
   do_stuff2(a);
   a = do_stuff1();
   udp->async_read( ..., read_handler );
}

periodic_handler(...)
{
  // do periodic stuff
  timer.async_wait( ..., periodic_handler );
}

main()
{
   ...
   a = do_stuff1();
   udp->async_read( ..., read_handler )
   timer.async_wait( ..., periodic_handler );

   io_service.run();
}

现在我确定您的问题中还有其他要求不明显,但您需要找出对它们的异步答案,这只是一个想法。还要问自己是否真的需要异步框架或只使用同步套接字 API。

于 2013-03-24T21:42:14.410 回答