2013-03-24 130 views
4

我已閱讀了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

回答

3

爲避免在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

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。

+0

由於他試圖在60hz運行,他需要小心計時器分辨率......看起來像asio提供了一個high_resolution_timer typedef,可以解決這個問題(沒有直接使用它)。 – 2013-03-26 14:27:01

+0

@NathanMonteleone:是的。我認爲在大多數平臺上,截止時間定時器將提供1ms的分辨率,但這需要驗證。如果你對某些抖動還可以,但不想積累也很容易做到的錯誤。如果您遇到更難的實時要求,這會變得更復雜一點。 – 2013-03-26 18:34:05