socket select()函數用於定時檢查以創建的socket句柄的狀態,以確定設定的socket句柄當前是否可寫或有數據可讀。
select函數提供了一種方法,使得程序在操作socket時(如recv操作),無需因阻塞而等待直至超時。特別是在一個線程中操作多個socket時,對多個socket逐一操作直至超時將浪費大量時間。
select機制則是同時對多個socket句柄進行監控,一旦存在可操作的socket,函數及返回並通知程序。
select函數聲明:
int select(
int nfds,
fd_set* readfds,
fd_set* writefds,
fd_set* exceptfds,
const struct timeval* timeout
);
fd_set是一個結構體,包含了一個SOCKET數組及一個整數用於表示數組中有效的SOCKET句柄數。
readfds參數,用於指示select函數:當其中包含的socket句柄可讀時,函數返回。
writefds和exceptfds則分別表示其中包含的socket句柄可寫或異常時,函數返回。
timeout是一個時間值結構,表示當前select函數執行時的超時時間,如果所有socket暫時都沒有可操作事件發生,則函數將一直等待直至超時,如果timeout設置為NULL時,select()函數則一直等到包含的socket存在操作事件時才返回。
select函數的返回值是一個整數。
如果執行異常,比如,指定的socket句柄是非法的等等,函數將返回SOCKET_ERROR,也就是-1.
如果select函數執行超時,即在指定的timeout時間內,沒有可操作的socket出現,那麼返回0.
其余情況函數將返回一個大於0的整數,用於指明可操作的socket總數。
由於select只返回一個表示總數的整數,那麼如果一次select多個socket句柄,或者函數執行時即指定了readfds,也指定了writefds,函數本身將無法告訴程序到底哪個socket句柄可讀或可寫。
所以在使用select時,盡量只指定檢查一個操作狀態。
不過對於同步阻塞的socket操作,writefds參數用到的機會可能會比較少。
示例: