2010-05-26 30 views
1

嘿,我正在寫一個udp客戶端服務器,其中一個客戶端等待來自服務器的數據包。但是我想限制這個等待一定的時間。客戶端在某個時刻沒有得到響應發出警報,基本上它出來了,並開始採取補救措施。那麼它有什麼可能的解決方案。我認爲圍繞recv寫一個包裝將起作用,但究竟該如何完成,我的意思是如何使recv升起警報你在此之後的時間限制。C,C++的中斷機制

任何在這方面的幫助將不勝感激。

謝謝!

回答

6

如果你想用超時進行套接字通信,那麼select是要走的路。

您基本上爲各種事件設置了文件描述符數組,例如read-ready或write-able,然後在超時時調用select。如果其中一個事件有效,您將收到通知,您可以執行您的操作。

如果在超時之前沒有發生任何事件,您仍會收到通知,並且可以採取您認爲合適的任何補救措施。

查看here血淋淋的細節,擴展如下。

或者,你可以使用setsockopt與SO_RCVTIMEO:

struct timeval tv; 
tv.tv_sec = 5; 
tv.tv_used = 0; 
setsockopt (socket_id, SOL_SOCKET, SO_RCVTIMEO, 
    &tv, sizeof(struct timeval)); 

要詳細瞭解select,您使用FD_ZEROFD_SET宏構建一組感興趣文件描述符(fdsets)給你。您可以有三組,一組指示一個或多個fds是否有數據要讀取,一個指示是否有一個或多個準備好寫入,另一個指示錯誤。你可能不一定擁有全部三個,這取決於你的代碼在做什麼。

一旦你設置了fdsets,你就可以將它們連同fds的數量和超時時間一起傳遞給select,它編織它的魔法並返回給你。在執行此操作之前,請製作fdset的副本(FD_COPY)以供日後恢復。

返回時,出現錯誤,超時或與感興趣的某個fds有關的事件。在後一種情況下,fdsets已被修改爲僅爲具有事件的那些設置了fds,並且您可以使用FD_ISSET來檢測哪些fds。

然後,一旦處理了所有事件,請使用FD_COPY恢復原始fdsets(記住它們被修改爲select),並再次調用select。繼續,只要你需要。

請記住,從select返回的錯誤不一定是致命的。如果處理信號,您可以獲得(在errnoEAGAIN暫時資源短缺或EINTR。對於第二種情況,您可以重新輸入選擇呼叫。首先,我會實施一個重試循環,以防只是暫時的事情。

+0

thansk for the reply。 – mawia 2010-05-26 09:46:54

+0

嗨! 有沒有什麼辦法知道使用select,在哪個文件描述符操作發生?我的意思是,如果我們正在傳遞一個文件描述符,我們顯然需要一些關於返回select的信息,關於哪個文件描述符在哪已經發生,因爲它將有助於採取進一步的行動。 謝謝! – mawia 2010-05-26 15:45:36

+1

是的,描述符集是_modified_,以便只設置具有事件的位。如果錯誤(select errno),select'將返回-1,否則超時時返回0。如果你得到一個積極的ineteger,然後你使用FD_ISSET來檢查集合中的每個文件描述符。只要確保在重新調用select之前重新初始化fd集。 – paxdiablo 2010-05-26 15:53:49

1

您可以使用select(...)並將非零超時作爲最後一個參數。這是最便攜的方式。

你也可以使用信號,但這不是可移植的,即使在有系統的系統上,它也可能不像你預期的那樣工作。 (信號處理程序完成後,recv/select/whatever可能會重新啓動,從而破壞整個目的。)

+0

感謝您的回覆。 – mawia 2010-05-26 09:47:13