關(guān)于select函數(shù):
其函數(shù)原型為:
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
此函數(shù)的功能是由內(nèi)核檢測(cè)在timeout時(shí)間內(nèi),是否有readfds,writefds,exceptfds三個(gè)句柄集(file descriptors)里的某個(gè)句柄(file descriptor)的狀態(tài)符合尋求,即readfds句柄集里有句柄可讀或writefds句柄集里有可寫(xiě)或exceptfds句柄集里有例外發(fā)生,任何一個(gè)有變化函數(shù)就立即返回,返回值為timeout發(fā)生狀態(tài)變化的句柄個(gè)數(shù)。
n是所有readfds,writefds,exceptfds三個(gè)句柄集(file descriptors)里編號(hào)最大值加1。比如:要檢測(cè)兩個(gè)socket句柄fd1和fd2在timeout時(shí)間內(nèi)是否分別可讀和可寫(xiě)就可以這樣:
先把兩個(gè)句柄集(file descriptors)清零:
FD_ZERO (&readfds);
FD_ZERO (&writefds);
然后把fd1加入讀檢測(cè)集:
FD_SET (fd1, &readfds);
然后把fd2加入寫(xiě)檢測(cè)集:
FD_SET (fd2, &writefds);
再給timeout設(shè)置值,timeout是這樣的一個(gè)結(jié)構(gòu):
struct timeval {
long tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
你可以這樣賦值:
timeout.tv_sec=1;
timeout.tv_uec=0;
表示檢測(cè)在1秒鐘內(nèi)是否有句柄狀態(tài)發(fā)生變化。
如果有句柄發(fā)生變化,就可以用FD_ISSET檢測(cè)各個(gè)句柄,比如:
FD_ISSET (fd1, &readfds);//檢測(cè)是否fd1變成可讀的了
FD_ISSET (fd2, &writefds);//檢測(cè)是否fd2變成可寫(xiě)的了
示意程序代碼如下:
/*----------------------示意代碼開(kāi)始--------------------------------------------*/ fd1 = socket();//創(chuàng)建一個(gè)socket fd2 = socket();//創(chuàng)建一個(gè)socket while(1) { FD_ZERO (&readfds); FD_ZERO (&writefds); FD_SET (fd1, &readfds); FD_SET (fd2, &writefds); timeout.tv_sec=1; timeout.tv_uec=0; ret = select(fd1>fd2?(fd1+1):(fd2+1), &readfds, &writefds, NULL, &timeout); if(ret < 0) {printf("系統(tǒng)錯(cuò)誤,select出錯(cuò),錯(cuò)誤代碼:%d, 錯(cuò)誤信息:%s", errno, strerror(errno));} else if(ret == 0) {printf("select超時(shí)返回,沒(méi)有任何句柄狀態(tài)發(fā)生變化!");} //有句柄狀態(tài)發(fā)生了變化 if(FD_ISSET(fd1, &readfds)) { fd1有數(shù)據(jù)可讀; fd1里的數(shù)據(jù)被讀出來(lái); } if(FD_ISSET(fd2, &writefds)) { fd2可寫(xiě); fd2里發(fā)送數(shù)據(jù)給對(duì)方; } } /*----------------------示意代碼結(jié)束--------------------------------------------*/ |