升压异步UDP客户端

问题描述:

我已阅读了boost:asio文档(它在异步客户端上显示为无声),并通过此处查看,但似乎无法在此找到树的森林。升压异步UDP客户端

我有,有一个主循环看起来像这样的模拟:

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()块的时间超过2ms,因为main for循环需要以60Hz执行。
  3. 服务器将在别处运行,并且具有完全不稳定的时间表。有时候不会有数据,我可能会重复地获得同一个数据包。

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

我想过关闭套接字读取超时,但似乎你必须作弊和摆脱增强呼叫来做到这一点,所以这是一个非起动器。

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

+0

+1不错的第一个问题,欢迎来到SO – 2013-03-25 00:51:23

+0

很长时间潜伏者,第一次海报。我将不得不做的下一步reddit :) – Grommit 2013-03-25 13:57:18

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

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

+1

谢谢。我并不太在意网络丢包等,我只是不希望有一个实例,我只有5%的时间在积极寻找,因此错过了95%的数据包。如果他们闲逛了一段时间等待以后收集,那么我没事。 – Grommit 2013-03-24 21:29:47

+0

使用异步读取将允许操作系统接收数据包并在调用'run','run_one','poll'或'poll_one'时传递它们。 – TAS 2013-03-24 21:34:57

+0

@Grommit当你使用像poll_one这样的东西时,你需要小心一点,就是排队等候的东西太多,并且落后于服务器(特别是如果由于某种原因,你的主循环必须暂停一段时间)。 – 2013-03-26 14:35:24

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

  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。

+0

由于他试图在60hz运行,他需要小心计时器分辨率......看起来像asio提供了一个high_resolution_timer typedef,可以解决这个问题(没有直接使用它)。 – 2013-03-26 14:27:01

+0

@NathanMonteleone:是的。我认为在大多数平台上,截止时间定时器将提供1ms的分辨率,但这需要验证。如果你对某些抖动还可以,但不想积累也很容易做到的错误。如果您遇到更难的实时要求,这会变得更复杂一点。 – 2013-03-26 18:34:05