2016-10-16 70 views
3

我正在寫一個非分岔服務器,使用poll()進行多個同時連接。它工作正常,除了我有問題如何檢測超時正確的方式。如何使用poll()檢測超時客戶端?

比方說,我有以下代碼:

#define POLL_SIZE 512 

struct pollfd poll_set[POLL_SIZE]; 
timeout = 60000; // 60 secs 

// setup server_sockfd with socket(), bind(), listen(), ... 

poll_set[0].fd = server_sockfd; 
poll_set[0].events = POLLIN; 
numfds = 1; 

while(1) { 
    rc = poll(poll_set, numfds, timeout); 
    if(rc == 0){ 
     // handle timeout 
    } 

    for(fd_index = 0; fd_index < numfds; fd_index++) { 
     if(poll_set[fd_index].revents & POLLIN) { 
     // accept new connection or handle established connections 
     } 
    } 
} 

假設,我有15個客戶端連接,14個客戶端發送和接收數據,但一個客戶是沉默,沒有數據或者從,即。只需佔用服務器上的一個套接字即可。現在

,問題是,民意調查()不能當場這個特定的客戶端,因爲所有其他14個客戶端提供數據,所以民調()說,它的確定。

你將如何通過檢測這個沉默的客戶解決了這個問題,並關閉它的連接?

目前,我還沒有更好的,然後創建一個time_t lastseen [POLL_SIZE]數組,並且當從客戶端讀取數據或發送到客戶端時跟蹤給定連接的時間戳。

然後我在每60秒,使用報警信號,並通過lastseen陣列運行時,比較其與當前時間戳的時間戳,和拆除每個連接爲空閒> 60秒。

或許一個線程可以做,以避免信號是相同的。你有什麼建議來解決這個問題?

(請注意,我嘗試用libevent的,這是非常好的。但是,我不得不放棄,因爲我找不到支持SSL/TLS添加到已經連接的套接字。想想STARTTLS的)

回答

0

檢測與套接字相關的錯誤不是輪詢的工作。它所做的只是表明一個或多個套接字是否準備好進行讀寫操作。如果任何等待的套接字都發生錯誤,那麼在revents字段中指示套接字已準備就緒(實際上由OS標記)和POLLERR標誌。

什麼時間超時。通常,超時不是傳輸層錯誤(因此不會被套接字跟蹤)。你需要自己跟蹤它。例如,您可以記住上次從套接字讀取的時間戳(請參閱clock_gettime(CLOCK_MONOTONIC,...)),並將輪詢超時設置爲與該套接字相關的所有超時的最小值。超時過期後,您需要檢查每個套接字是否過期或者不是。

也可以考慮使用epoll的 - 這是快得多大量調查一個插座。此外,對於選擇最近的超時,您可以使用堆數據結構。因此,您可以使用O(log n)執行時間管理所有套接字。

+0

謝謝梅德,然後我會跟蹤給定的插座自己的時間戳。比 –

+0

感謝與clock_gettime的提示。順便說一句。儘管我開發的軟件主要在Linux上運行,但我仍想繼續支持其他操作系統(例如Freebsd等)支持民意測驗。 –