2013-04-24 64 views
2

我想使用select()從其他服務器接收更新併發送定期消息。考慮以下設置:在套接字編程的select()中重新啓動定時器

while(1){ select(... timeout = 5 seconds); //一些其他代碼}

如果我在t = 2時秒接收更新,然後的select()將返回與相應的語句將被執行。當下一個循環開始時,超時將再次設置爲5秒。但是,它應該是5 - 2 = 3秒。有沒有辦法在正確的時間更新計時器?

我想在select()之前手動啓動定時器righr,但是這個定時器可能與select()中使用的定時器不同步。並會導致其他潛在的問題。

回答

3

按照select man page

在Linux上,select()修改超時反映的時間不睡覺的金額;大多數其他實現不這樣做。 (POSIX.1-2001允許任一行爲。)

所以,你只是簡單地重用timeout變量。你只有在你真的超時時重置它的價值。

正如警告所示,依靠此行爲會導致移植問題,因此如果您依賴此行爲,請確保將其記錄下來,以便在移植代碼時完成正確的操作。

+0

我在windows機器上編碼,但程序將在Linux上測試。那麼每次重新設置超時會更好一些,這樣可以避免移植問題? – whileone 2013-04-24 01:20:58

+0

是的,你可以這樣做(如@MichalRus建議)。或者,您可以創建一個單獨的線程來執行定期處理。該線程可以只休眠5秒,然後在循環中執行一些操作。 – jxh 2013-04-24 01:41:51

+0

有你。謝謝! – whileone 2013-04-24 02:22:16

1

只要記住time()在一個變量調用select()之前,再弄time()select()回報,......在接下來的while(1)重複使用不5,但5 - difference_between_times超時值。

也許你會想用new_timeout = 5 - difference_between_times % 5,這樣,如果以後select回報操作需要更長的時間超過5秒......你還是設置在timeout 5秒的時間間隔。

您可能應該使用不是秒,而是使用更細化的時間單位。並考慮以上是否是你真正想要的行爲(以模爲單位)。也許當difference_between_times > 5,你應該等待5秒。按照你的意願去做,但你明白了。

1

當你的應用程序變得更復雜一些時,你可能會有多個定時器具有不同的超時間隔。我們的確是。這是我們如何處理它。

每個定時器都有一個定時器對象,其中有一個time_t定時器到期。我們將所有的定時器存儲在堆數據結構中,因此最快的定時器將位於堆的根部。在執行select()之前,我們獲取堆的根,並從計時器的到期時間中減去當前時間,並將該delta用作select()調用的超時時間。

Timer * t = heap->Root(); 
time_t now = time(0); 
timeval tv; 
tv.tv_sec = t->when - now; 
tv.tv_usec = 0; 
select(... & tv); 
相關問題