fd_set 用法
http://www.cnblogs.com/wolflion/archive/2011/07/13/2539137.html
select()函數主要是建立在fd_set類型的基礎上的。fd_set(它比較重要所以先介紹一下)是一組文件描述字(fd)的集合,它用一位來表示一個fd(下面會仔細介紹),對于fd_set類型通過下面四個宏來操作:?
fd_set set;
FD_ZERO(&set);??????
FD_SET(fd, &set);???
FD_CLR(fd, &set);???
FD_ISSET(fd, &set);????????
過去,一個fd_set通常只能包含<32的fd(文件描述字),因為fd_set其實只用了一個32位矢量來表示fd;現在,UNIX系統通常會在頭文件<sys/select.h>中定義常量FD_SETSIZE,它是數據類型fd_set的描述字數量,其值通常是1024,這樣就能表示<1024的fd。根據fd_set的位矢量實現,我們可以重新理解操作fd_set的四個宏:?
fd_set set;
FD_ZERO(&set);?????
FD_SET(0, &set);???
FD_CLR(4, &set);?????
FD_ISSET(5, &set);???
―――――――――――――――――――――――――――――――――――――――
注意fd的最大值必須<FD_SETSIZE。
―――――――――――――――――――――――――――――――――――――――?
select函數的接口比較簡單:
int select(int nfds, fd_set *readset, fd_set *writeset,
fd_set* exceptset, struct tim *timeout);?
功能:
測試指定的fd可讀?可寫?有異常條件待處理??????
參數:
nfds:?需要檢查的文件描述字個數(即檢查到fd_set的第幾位),數值應該比三組fd_set中所含的最大fd
???????值更大,一般設為三組fd_set中所含的最大fd值加1(如在readset,writeset,exceptset中所含最大
???????的fd為5,則nfds=6,因為fd是從0開始的)。設這個值是為提高效率,使函數不必檢查fd_set的所
???????有1024位。
readset:??用來檢查可讀性的一組文件描述字。
writeset: 用來檢查可寫性的一組文件描述字。
exceptset:用來檢查是否有異常條件出現的文件描述字。(注:錯誤不包括在異常條件之內)
timeout:有三種可能:
?????????1:timeout=NULL(阻塞:直到有一個fd位被置為1函數才返回)
?????????2:timeout所指向的結構設為非零時間(等待固定時間:有一個fd位被置為1或者時間耗盡,函數
????????????均返回)
?????????3.?timeout所指向的結構,時間設為0(非阻塞:函數檢查完每個fd后立即返回)?
返回值:?????
返回對應位仍然為1的fd的總數。?
Remarks:
三組fd_set均將某些fd位置0,只有那些可讀,可寫以及有異常條件待處理的fd位仍然為1。
使用select函數的過程一般是:
先調用宏FD_ZERO將指定的fd_set清零,然后調用宏FD_SET將需要測試的fd加入fd_set,接著調用函數??
select測試fd_set中的所有fd,最后用宏FD_ISSET檢查某個fd在函數select調用后,相應位是否仍然為1。?
以下是一個測試單個文件描述字可讀性的例子:
int isready(int fd)
{
????int rc;
????fd_set fds;
????struct tim tv;????
????FD_ZERO(&fds);
????FD_SET(fd,&fds);
????tv.tv_sec = tv.tv_usec = 0;????
????rc = select(fd+1, &fds, NULL, NULL, &tv);
????if (rc < 0)???//error
????????return -1;????
????return FD_ISSET(fd,&fds) ? 1 : 0;
?}
下面還有一個復雜一些的應用:
//這段代碼將指定測試Socket的描述字的可讀可寫性,因為Socket使用的也是fd
uint32 SocketWait(TSocket *s,bool rd,bool wr,uint32 timems)????
{
?????fd_set rfds,wfds;
?#ifdef _WIN32
?????TIM tv;
?#else
?????struct tim tv;
?#endif????
?????FD_ZERO(&rfds);
?????FD_ZERO(&wfds);?
?????if (rd)???//TRUE
?????FD_SET(*s,&rfds);???//添加要測試的描述字?
?????if (wr)?????//FALSE
???????FD_SET(*s,&wfds);?
?????tv.tv_sec=timems/1000;?????//second
?????tv.tv_usec=timems00;?????//ms?
?????for (;;) //如果errno==EINTR,反復測試緩沖區的可讀性
??????????switch(select((*s)+1,&rfds,&wfds,NULL,
??????????????(timems==TIME_INFINITE?NULL:&tv)))??//測試在規定的時間內套接口接收緩沖區中是否有數據可讀
?????????{ ?????????????????????????????????????????????//0--超時,-1--出錯
?????????case 0:????
??????????????return 0;?
?????????case (-1):???
??????????????if (SocketError()==EINTR)
???????????????????break;??????????????
??????????????return 0; //有錯但不是EINTR?
??????????default:
??????????????if (FD_ISSET(*s,&rfds)) //如果s是fds中的一員返回非0,否則返回0
???????????????????return 1;
??????????????if (FD_ISSET(*s,&wfds))
???????????????????return 2;
??????????????return 0;
?????????};
?
}
轉載于:https://www.cnblogs.com/johnnyflute/p/3800984.html
總結
- 上一篇: ssh连接远程主机执行脚本的环境变量问题
- 下一篇: 汉字转html实体符号js_js转htm