【问题标题】:Boost Async UDP Client提升异步 UDP 客户端
【发布时间】:2013-03-24 20:22:23
【问题描述】:

我已通读 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 调用才能做到这一点,所以这是行不通的。

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

【问题讨论】:

  • +1 不错的第一个问题,欢迎来到 SO
  • 长期潜伏者,第一次发帖。接下来我将不得不做 reddit :)

标签: sockets boost asynchronous udp boost-asio


【解决方案1】:

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

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

【讨论】:

  • 谢谢。我不太担心网络丢弃数据包等......我只是不想有一个实例,我只在 5% 的时间里积极寻找,因此设计时错过了 95% 的数据包。如果他们闲逛一段时间以等待以后收集,那我没问题。
  • 使用异步读取将允许操作系统在您调用runrun_onepollpoll_one 时接收数据包并传送它们。
  • @Grommit 使用 poll_one 之类的东西时需要注意的一件事是,有太多东西排队并落后于服务器(特别是如果由于某种原因你的主循环必须暂停一段时间)而)。
【解决方案2】:

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

  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。

【讨论】:

  • 由于他试图以 60hz 运行,他需要注意计时器分辨率...看起来 asio 提供了一个 high_resolution_timer typedef 可以解决这个问题(没有直接使用它)。
  • @NathanMonteleone:是的。我认为在大多数平台上,截止时间计时器将提供 1 毫秒的分辨率,但这需要验证。如果您可以接受一些抖动但不想累积错误,这也很容易做到。如果您遇到更难的实时要求,这会变得有点复杂。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 2019-09-09
  • 1970-01-01
  • 1970-01-01
  • 2014-06-29
  • 1970-01-01
相关资源
最近更新 更多