阻塞方式block,就是程序或是執行緒執行到這些函式時必須等待某個事件的發生,如果事件沒有發生,程序或執行緒就被阻塞,函式不能立即返回。使用select就可以完成非阻塞non-block,就是程序或執行緒執行此函式時不必非要等待事件的發生,一旦執行肯定返回,以返回值的不同來反映函式的執**況,如果事件發生則與阻塞方式相同,若事件沒有發生則返回乙個**來告知事件未發生,而程序或執行緒繼續執行,所以效率較高。select能夠監視我們需要監視的檔案描述符的變化情況。
(一)首先說明兩個結構體:
1:struct fd_set乙個存放檔案描述符(file descriptor),即檔案控制代碼的聚合,實際上是一long型別的陣列,每乙個陣列元素都能與一開啟的檔案控制代碼(不管是socket控制代碼,還是其他檔案或命名管道或裝置控制代碼)建立聯絡,建立聯絡的工作由程式設計師完成;
fd_zero(fd_set *fdset):清空fdset與所有檔案控制代碼的聯絡。
fd_set(intfd, fd_set *fdset):建立檔案控制代碼fd與fdset的聯絡。
fd_clr(intfd, fd_set *fdset):清除檔案控制代碼fd與fdset的聯絡。
fd_isset(intfd, fdset *fdset):檢查fdset聯絡的檔案控制代碼fd是否可讀寫,>0表示可讀寫。
2:struct timeval用來代表時間值,有兩個成員,乙個是秒數tv_sec,另乙個是毫秒數tv_usec。
(二)下面介紹select()函式原型:
1:int select(int nfds, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)
2:ndfs:select中監視的檔案控制代碼數,一般設為要監視的檔案中的最大檔案號加一。
3:rdfds:select監視的可讀檔案控制代碼集合,當rdfds映象的檔案控制代碼狀態變成可讀時系統告訴select函式返回。
這個集合中有乙個檔案可讀,select就會返回乙個大於0的值,表示有檔案可讀;如果沒有可讀的檔案,則根據timeout引數再判斷是否超時,若超出timeout的時間,select返回0,若發生錯誤返回負值;可以傳入null值,表示不關心任何檔案的讀變化;
4:wtfds: select監視的可寫檔案控制代碼集合,當wtfds映象的檔案控制代碼狀態變成可寫時系統告訴select函式返回。
如果這個集合中有乙個檔案可寫,select就會返回乙個大於0的值,表示有檔案可寫;如果沒有可寫的檔案,則根據timeout引數再判斷是否超時,若超出timeout的時間,select返回0,若發生錯誤返回負值;可以傳入null值,表示不關心任何檔案的寫變化。
5:exfds:select監視的異常檔案控制代碼集合,當exfds映象的檔案控制代碼上有特殊情況發生時系統會告訴select函式返回。
6:timeout:select的超時結束時間。
這個引數它使select處於三種狀態,
第一,若將null以形參傳入,即不傳入時間結構,就是將select置於阻塞狀態,一定等到監視檔案描述符集合中某個檔案描述符發生變化為止;
第二,若將時間值設為0秒0毫秒,就變成乙個純粹的非阻塞函式,不管檔案描述符是否有變化,都立刻返回繼續執行,檔案無變化返回0,有變化返回乙個正值;
第三,timeout的值大於0,這就是等待的超時時間,即select在timeout時間內阻塞,超時時間之內有事件到來就返回了,否則在超時後不管怎樣一定返回,返回值同上述。
7:返回值:負值:select錯誤
0:等待超時,沒有可讀寫或錯誤的檔案
正值:某些檔案可讀可寫或出錯
(三)下面是乙個有三個套接字控制代碼的例子
intsa, sb, sc;
sa = socket(...);
connect(sa,...);
sb = socket(...);
connect(sb,...);
sc = socket(...);
connect(sc,...);
fd_set(sa, &rdfds);/* 分別把3個控制代碼加入讀監視集合裡去 */
fd_set(sb, &rdfds);
fd_set(sc, &rdfds);
intmaxfd = 0;
if(sa > maxfd) maxfd = sa;/* 獲取3個控制代碼的最大值 */
if(sb > maxfd) maxfd = sb;
if(sc > maxfd) maxfd = sc;
structtimeval tv;
tv.tv_sec = ... ;
tv.tv_usec = ...;
ret = select(maxfd + 1, &rdfds, null, null, &tv); /* 注意是最大值加1 */
if(ret < 0)
elseif(ret == 0)
else
if(fd_isset(sb, &rdfds)) /* 斷一下sb這個被監視的控制代碼是否真的變成可讀的了 */
if(fd_isset(sc, &rdfds)) /* 斷一下sc這個被監視的控制代碼是否真的變成可讀的了 */
}
Select 函式詳細介紹
linux下select函式的使用 一.select 函式詳細介紹 負值 select錯誤 正值 某些檔案可讀寫或出錯 0 等待超時,沒有可讀寫或錯誤的檔案 在有了select後可以寫出像樣的網路程式來!舉個簡單的例子,就是從網路上接受資料寫入乙個檔案中。二.另乙個例子 include includ...
select函式及fd set介紹
在程式設計的過程中,經常會遇到許多阻塞的函式,好像read和網路程式設計時使用的recv,recvfrom函式都是阻塞的函式,當函式不能成功執行的時候,程式就會一直阻塞在這裡,無法執行下面的 這是就需要用到非阻塞的程式設計方式,使用select函式就可以實現非阻塞程式設計。select函式是乙個輪循...
網路程式設計 select介紹
一 select函式簡介 select一般用在socket網路程式設計中,在網路程式設計的過程中,經常會遇到許多阻塞的函式,網路程式設計時使用的recv,recvfrom connect函式都是阻塞的函式,當函式不能成功執行的時候,程式就會一直阻塞在這裡,無法執行下面的 這是就需要用到非阻塞的程式設...