2012-02-23 219 views
1

所以我完全失去了它,當有人使用select()像我展示了一些代碼:SOCKET文件描述

FD_ZERO(&readfds); 
FD_SET(socket,&readfds); 
FD_SET(0,&readfds); 
.......// bind() and listen(),regular stuff 
// Before select(),this guy cleared readfds to null and sort of start all over again 
FD_ZERO(&readfds);// Behold,this is exactly the line confusing myself 
FD_SET(socket,&readfds); 
// select will be called in the future within a infinite loop 

所以基本上說什麼FD_ZERO綁定後,聽是由於某種原因,明確以前的內容,並插入插座文件描述符再次設置爲fd。同時,在fd集中,0描述符(標準輸入)顯然消失。

誰能解釋這件事?我不覺得這是正確的,但我不能真正弄清楚。也許再次設置一些特定的FD設置是一種實際的機制...

我認爲bind()listen()可以修改fd集以某種方式。我設置了幾個斷點,並檢查輸出。隨後,FD集沒有改變。

UPDATE:

真正讓我困惑的是第二FD_ZERO(&readfds)。 顯然,第一個就像在緩衝區中清理生鏽的東西。在每次迭代中,我們必須將fdset清除爲未來的默認值。我只是不理解第二個。要麼是錯誤的,要麼不會傷害到任何人。

+1

'select'會改變fdset,但'bind'和'listen'不能,它們甚至沒有指向它的指針。但是請自己幫忙,並使用像'poll'或'epoll'這樣的現代API,並且不要再擔心fdset。 – 2012-02-23 03:18:23

+0

聽起來很酷,但我不能得到它 – jasonkim 2012-02-23 03:20:57

+1

使用'民意測驗'。它現代,便攜和快速。 'epoll'僅用於基準自我愉悅,它擅長的基準測試不符合大多數真實世界的使用需求(其中'epoll'實際上比'poll'慢得多)。 – 2012-02-23 03:50:41

回答

4

不知道從哪裏你的困惑所在,但這裏的一個解釋。

的fdset是從0開始索引文件描述符位掩碼(在技術上,我不認爲它是一個位掩碼,但任何其他的實現是......怪)。

因此,一個fdset可能是這樣的:

   Byte 0        Byte 1 
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+ 
|fd0|fd1|fd2|fd3|fd4|fd5|fd6|fd7| |fd8|fd9|fd10|fd11|fd12|fd13|fd14|fd15| 
+---+---+---+---+---+---+---+---+ +---+---+----+----+----+----+----+----+ 

的想法是,你定了位爲給定的FD(文件描述符),如果你對它感興趣。如果你對它不感興趣,你就清楚了。

FD_ZERO將清除所有位,這是一個很好的起點。然後將兩個FD_SET調用將用於fd0(標準輸入)和fd<socket>位的設定。

然後,如果其中一個出現了在插座上(標準輸入或動作動作類型將取決於哪個參數位置,你傳遞fdset到select時使用的動作使用fdset一個選擇調用將返回。傳它作爲讀取fdset意味着如果你能夠讀取套接字或者在標準輸入中顯示出某些內容(例如使用鍵盤),就會返回。

這可能對代碼很有用「聊天」的應用,因爲它會等待從你或你的朋友在另一端輸入。

你之所以公頃已經重新調零並重新設置這些位中的fdset是因爲select本身修改所述一組,以指示什麼FD(或FDS)它檢測到的動作。

示例:如果有東西通過套接字進入,而沒有通過標準輸入進入,則fdset將被修改select以僅設置該位。這樣你就可以用FD_ISSET來檢測你應該看哪個fds。


如果,你似乎在註釋中指出,有兩個FD_ZERO()/FD_SET()序列之間(使用readfds或其它呼叫),則沒有select電話,是的,看來首先是不必要的,因爲信息將被第二個覆蓋。

沒有看到完整的代碼或建築設計文檔:-),很難說。

+0

讓我感到困惑的是代碼實際上很清晰,並且自己讀了兩次。 – jasonkim 2012-02-23 03:16:45

+0

@ y26jin,這是因爲'select'修改了數組 - 我添加了答案來擴展它。 – paxdiablo 2012-02-23 03:24:23

+0

我的意思是,第二個在select()修改任何東西之前被調用。 – jasonkim 2012-02-23 03:26:58

1

Select()用於當您試圖同時偵聽多個套接字時。每當你接受()一個套接字連接時,一個套接字描述符被返回,你用它來發送/接收文件。

當你做一個FD_SET你添加一個套接字描述符(它可能是讀/寫)。 FD_ZERO清除該特定集合中的所有條目。

因此,基本上每次接受連接時都可以將套接字描述符添加到套件中(即如果要使用該套接字來讀/寫)。

當您調用select()函數時,您可以指定要使用的集合。 (例如:readfds)和select()輪詢所有已經在該組中的套接字(readfds)。

欲瞭解更多信息,請閱讀beej's guide to network programing。它是一個非常好的教程來學習。

0

select(2)修改它的參數fd集,所以你應該在每次迭代時重新初始化它們。