select函式相關

2021-08-20 06:40:55 字數 3007 閱讀 2018

select在socket程式設計中還是比較重要的,可是對於初學socket的人來說都不太愛用select寫程式,他們只是習慣寫諸如connect、accept、recv或recvfrom這樣的阻塞程式(所謂阻塞方式block,顧名思義,就是程序或是執行緒執行到這些函式時必須等待某個事件的發生,如果事件沒有發生,程序或執行緒就被阻塞,函式不能立即返回)。可是使用select就可以完成非阻塞(所謂非阻塞方式non-block,就是程序或執行緒執行此函式時不必非要等待事件的發生,一旦執行肯定返回,以返回值的不同來反映函式的執**況,如果事件發生則與阻塞方式相同,若事件沒有發生則返回乙個**來告知事件未發生,而程序或執行緒繼續執行,所以效率較高)方式工作的程式,它能夠監視我們需要監視的檔案描述符的變化情況——讀寫或是異常。下面詳細介紹一下! 

select的函式格式(我所說的是unix系統下的伯克利socket程式設計,和windows下的有區別,一會兒說明): 

int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout); 

先說明兩個結構體: 

第一,struct fd_set可以理解為乙個集合,這個集合中存放的是檔案描述符(file descriptor),即檔案控制代碼,這可以是我們所說的普通意義的檔案,當然unix下任何裝置、管道、fifo等都是檔案形式,全部包括在內,所以毫無疑問乙個socket就是乙個檔案,socket控制代碼就是乙個檔案描述符。fd_set集合可以通過一些巨集由人為來操作,比如清空集合fd_zero(fd_set *),將乙個給定的檔案描述符加入集合之中fd_set(int ,fd_set *),將乙個給定的檔案描述符從集合中刪除fd_clr(int ,fd_set*),檢查集合中指定的檔案描述符是否可以讀寫fd_isset(int ,fd_set* )。一會兒舉例說明。 

第二,struct timeval是乙個大家常用的結構,用來代表時間值,有兩個成員,乙個是秒數,另乙個是毫秒數。 

具體解釋select的引數: 

int maxfdp是乙個整數值,是指集合中所有檔案描述符的範圍,即所有檔案描述符的最大值加1,不能錯!在windows中這個引數的值無所謂,可以設定不正確。 

fd_set *readfds是指向fd_set結構的指標,這個集合中應該包括檔案描述符,我們是要監視這些檔案描述符的讀變化的,即我們關心是否可以從這些檔案中讀取資料了,如果這個集合中有乙個檔案可讀,select就會返回乙個大於0的值,表示有檔案可讀,如果沒有可讀的檔案,則根據timeout引數再判斷是否超時,若超出timeout的時間,select返回0,若發生錯誤返回負值。可以傳入null值,表示不關心任何檔案的讀變化。 

fd_set *writefds是指向fd_set結構的指標,這個集合中應該包括檔案描述符,我們是要監視這些檔案描述符的寫變化的,即我們關心是否可以向這些檔案中寫入資料了,如果這個集合中有乙個檔案可寫,select就會返回乙個大於0的值,表示有檔案可寫,如果沒有可寫的檔案,則根據timeout引數再判斷是否超時,若超出timeout的時間,select返回0,若發生錯誤返回負值。可以傳入null值,表示不關心任何檔案的寫變化。 

fd_set *errorfds同上面兩個引數的意圖,用來監視檔案錯誤異常。 

struct timeval* timeout是select的超時時間,這個引數至關重要,它可以使select處於三種狀態,第一,若將null以形參傳入,即不傳入時間結構,就是將select置於阻塞狀態,一定等到監視檔案描述符集合中某個檔案描述符發生變化為止;第二,若將時間值設為0秒0毫秒,就變成乙個純粹的非阻塞函式,不管檔案描述符是否有變化,都立刻返回繼續執行,檔案無變化返回0,有變化返回乙個正值;第三,timeout的值大於0,這就是等待的超時時間,即select在timeout時間內阻塞,超時時間之內有事件到來就返回了,否則在超時後不管怎樣一定返回,返回值同上述。 

返回值: 

負值:select錯誤 正值:某些檔案可讀寫或出錯 0:等待超時,沒有可讀寫或錯誤的檔案 

範例:

#include #include #include #include int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);

功能:允許乙個程序去操作多個檔案描述符,阻塞等待乙個或者是多個檔案描述符準備就緒,

當有乙個或者多個檔案描述符準備就緒,則函式立即返回

void fd_clr(int fd, fd_set *set);

將fd移除set集合

int fd_isset(int fd, fd_set *set);

判斷fd是否存在在set裡面

void fd_set(int fd, fd_set *set);

將fd新增到set集合裡面

void fd_zero(fd_set *set);

清空set集合

引數:nfds: 最大的檔案描述符加一

readfds: 讀檔案描述符集合

writefds:寫檔案描述符集合

exceptfds:其他或者異常檔案描述符集合

timeout: 設定超時時間

返回值:

成功:如果timeout = null 則返回準備就緒的檔案描述符的個數

如果timeout != null 超時後返回0

失敗:-1

+++++++++++++++++++++++++++++++++++++

struct timeval ;

+++++++++++++++++++++++++++++++++++++

struct timeval out_time;

fd_zero(&readfds);

fd_set(sockfd, &readfds);

out_time.tv_sec = 5;

out_time.tv_usec = 0;

if((num = select(maxfd + 1, &readfds, null, null, &out_time)) < 0)

fd set 用法 select函式相關

select 函式主要是建立在fd set型別的基礎上的。fd set 它比較重要所以先介紹一下 是一組檔案描述字 fd 的集合,它用一位來表示乙個fd 下面會仔細介紹 對於fd set型別通過下面四個巨集來操作 fd set set fd zero set fd set fd,set fd clr...

linux中select 函式相關

select 的機制中提供一fd set的資料結構,實際上是一long型別的陣列,每乙個陣列元素都能與一開啟的檔案控制代碼 不管是socket控制代碼,還是其他 檔案或命名管道或裝置控制代碼 建立聯絡,建立聯絡的工作由程式設計師完成,當呼叫select 時,由核心根據io狀態修改fd set的內容,...

select函式詳解

select的機制中提供了乙個fd set的資料結構,實際上是long型別的陣列,每乙個陣列元素都能與一開啟的檔案控制代碼 不管是socket控制代碼,還是其他檔案或命名管道或裝置控制代碼 建立聯絡,建立聯絡的工作由程式設計師完成,當呼叫select 時,由核心根據io狀態修改fd set的內容,由...