2012-05-27 38 views
2

我使用epoll來管理大約20到30個套接字。我發現epoll_wait可以用來等待一些數據到達其中一個套接字,但我錯過了如何在套接字級別實現超時。我可以在epoll_wait上使用超時,但在我的情況下它不是很有用。例如,如果我需要每關閉一個沒有記錄活動的套接字> 500毫秒,orr可能會每200毫秒發送一些數據到套接字,無論如何。這些套接字級別超時如何使用epoll實現?任何建議和想法,將不勝感激!epoll和超時

感謝, Shivam卡爾拉

回答

4

聽起來你想要寫一個事件循環(如果有的話看看libev BTW)。 epoll不會幫助你,你必須自己跟蹤套接字的不活動情況(例如,clock_gettime()gettimeofday()),然後每秒醒來幾次並檢查所需的一切。

一些僞代碼

while (1) { 
    n = epoll_wait(..., 5); 
    if (n > 0) { 
     /* process activity */ 
    } else { 
     /* process inactivity */ 
    } 
} 

這將喚醒你200次第二,如果所有插座都無效。

不活動檢查要求套接字的列表與上次活動的時間戳檢查一起:

struct sockstamp_s { 
    /* socket descriptor */ 
    int sockfd; 
    /* last active */ 
    struct timeval tv; 
}; 

/* check which socket has been inactive */ 
for (struct sockstamp_s *i = socklist; ...; i = next(i)) { 
    if (diff(s->tv, now()) > 500) { 
     /* socket s->sockfd was inactive for more than 500 ms */ 
     ... 
    } 
} 

其中diff()爲您提供了2個struct timeval S上的差異,now()給你當前的時間戳。

+0

感謝您的回覆。但是,我想知道,如果我可以使用epoll等待非常短的時間可以約10毫秒的無活動檢查?與select + inactivity chec相比,我能獲得任何性能改進嗎? – Shivam

+0

取決於你越會喚醒你消耗的CPU越多。而且,你需要一個1000 HZ的內核來喚醒每一毫秒。就像我說的那樣,我強烈建議一個準備好的事件循環(像libev或libevent),它們針對這些情況進行了優化(以依賴關係爲代價)。 – hroptatyr

3

嘗試將每個套接字與計時器fd對象配對(timerfd_create)。對於應用程序中的每個套接字,創建一個初始設置爲在500ms後過期的定時器,然後將定時器添加到epoll對象(與套接字通過epoll_ctlEPOLL_CTL_ADD相同)。然後,每當數據到達套接字時,將該套接字的關聯定時器重置爲500毫秒超時。

如果定時器到期(因爲套接字已經不活動500ms),那麼定時器將在epoll對象中變爲「已準備就緒」,並導致任何等待epoll_wait的線程喚醒。然後該線程可以處理定時器關聯套接字的超時。