2011-04-17 58 views
1
fd_set rset; 
struct timeval tv; 
FD_ZERO(&rset); 
FD_SET(sockfd, &rset); 
tv.tv_sec = 1; 
tv.tv_usec = 0; 

for(;;) 
{ 
    for(count = 0; count < elements in sockaddr_in array; count++) 
    { 
    //flag_array is filled with -1 before for(;;) 
    if(flag_array[count] == -1 && select(sockfd+1, &rset, NULL, NULL, &tv)) 
    { 
     recvfrom(...) 
    } 
    tv.tv_sec = 1; 
    FD_ZERO(&rset);//this fixed it 
    FD_SET(sockfd, &rset);//and this too 
    } 

    //contact everyone from sockaddr array (works like a charm!) 
} 

如果我不前的「超時」情況下,select語句「失敗」從我的其他程序發送我的信息給該節目,所以我不能使用recvfrom的聲明在裏面。我曾經這樣做過,以便我的其他程序在無限循環中與這個程序聯繫,但它從未進入if語句。有選擇和recvfrom意外的結果

什麼工作: 如果我在每次超時發生之前聯繫此程序,一切都很好。 如果我把recvfrom語句放在if(___ & & select)之外,它就可以工作得很好。

在此處,此程序將被稱爲的Recv一個小圖:

if(A contacts Recv before timeout) count = 0 
    Recv stores contact A in struct 
if(B contacts Recv before timeout) count = 1 
    Recv stores contact B in struct 
if(timeout)       count = 2 

if(C contacts Recv after timeout)  count = 3 
    nothing 
             count = 4 

程序將聯繫A和B就好 //追溯到開始循環

flag_array == -1 is false    count = 0 
flag_array == -1 is false    count = 1 
flag_array == -1 is true...select "fails" count = 2..3..4..(exit loop) 

的發佈之前2分鐘,我決定最後看一下我以前的代碼。我想我忘了

FD_ZERO(&rset); 
FD_SET(sockfd, &rset); 

for循環後(其中tv.tv_sec = 1)在。

有人可以詳細說明爲什麼有必要這樣做嗎?

回答

4

select()修改傳遞fd_set - 你必須每次調用select()之前對其進行設置。這只是select()應該如何工作。

3

這是必要的,因爲select()可能會修改文件描述符集。

the Linux manpage for select(3)舉例:

成功完成後,將PSELECT()或選擇()函數應修改的對象由readfds,writefds指出,和errorfds參數指示哪些文件描述符準備好讀取,準備寫入,或者有待處理的錯誤條件,並且應該返回所有輸出集合中已準備描述符的總數。對於每個小於nfds的文件描述符,如果在輸入上設置了相應的位,並且該文件描述符的相關條件爲真,則應在成功完成時設置相應的位。

請注意,select()也可以修改它的struct timeval參數,例如, Linux會在其中存儲已用時間。因此,您應該重置tv的所有字段。

+0

我發現'struct timeval'在再次調用'select()'之前需要重新設置,比如說它是在while循環中。 – 2015-11-17 05:25:23