poll()函數(shù):這個(gè)函數(shù)是某些Unix系統(tǒng)提供的用于執(zhí)行與select()函數(shù)同等功能的函數(shù),下面是這個(gè)函數(shù)的聲明: #include <poll.h> int poll(struct pollfd fds[], nfds_t nfds, int timeout); 參數(shù)說明: fds:是一個(gè)struct pollfd結(jié)構(gòu)類型的數(shù)組,用于存放需要檢測其狀態(tài)的Socket描述符;每當(dāng)調(diào)用這個(gè)函數(shù)之后,系統(tǒng)不會(huì)清空這個(gè)數(shù)組,操作起來比較方便;特別是對于 socket連接比較多的情況下,在一定程度上可以提高處理的效率;這一點(diǎn)與select()函數(shù)不同,調(diào)用select()函數(shù)之后,select() 函數(shù)會(huì)清空它所檢測的socket描述符集合,導(dǎo)致每次調(diào)用select()之前都必須把socket描述符重新加入到待檢測的集合中;因 此,select()函數(shù)適合于只檢測一個(gè)socket描述符的情況,而poll()函數(shù)適合于大量socket描述符的情況; nfds:nfds_t類型的參數(shù),用于標(biāo)記數(shù)組fds中的結(jié)構(gòu)體元素的總數(shù)量; timeout:是poll函數(shù)調(diào)用阻塞的時(shí)間,單位:毫秒; 返回值: >0:數(shù)組fds中準(zhǔn)備好讀、寫或出錯(cuò)狀態(tài)的那些socket描述符的總數(shù)量; ==0:數(shù)組fds中沒有任何socket描述符準(zhǔn)備好讀、寫,或出錯(cuò);此時(shí)poll超時(shí),超時(shí)時(shí)間是timeout毫秒;換句話說,如果所檢測的 socket描述符上沒有任何事件發(fā)生的話,那么poll()函數(shù)會(huì)阻塞timeout所指定的毫秒時(shí)間長度之后返回,如果timeout==0,那么 poll() 函數(shù)立即返回而不阻塞,如果timeout==INFTIM,那么poll() 函數(shù)會(huì)一直阻塞下去,直到所檢測的socket描述符上的感興趣的事件發(fā)生是才返回,如果感興趣的事件永遠(yuǎn)不發(fā)生,那么poll()就會(huì)永遠(yuǎn)阻塞下去; A timeout of INFTIM means** wait indefinitely.-1: poll函數(shù)調(diào)用失敗,同時(shí)會(huì)自動(dòng)設(shè)置全局變量errno; 如果待檢測的socket描述符為負(fù)值,則對這個(gè)描述符的檢測就會(huì)被忽略,也就是不會(huì)對成員變量events進(jìn)行檢測,在events上注冊的事件也會(huì)被 忽略,poll()函數(shù)返回的時(shí)候,會(huì)把成員變量revents設(shè)置為0,表示沒有事件發(fā)生; 另外,poll() 函數(shù)不會(huì)受到socket描述符上的O_NDELAY標(biāo)記和O_NONBLOCK標(biāo)記的影響和制約,也就是說,不管socket是阻塞的還是非阻塞 的,poll()函數(shù)都不會(huì)收到影響;而select()函數(shù)則不同,select()函數(shù)會(huì)受到O_NDELAY標(biāo)記和O_NONBLOCK標(biāo)記的影 響,如果socket是阻塞的socket,則調(diào)用select()跟不調(diào)用select()時(shí)的效果是一樣的,socket仍然是阻塞式TCP通訊,相 反,如果socket是非阻塞的socket,那么調(diào)用select()時(shí)就可以實(shí)現(xiàn)非阻塞式TCP通訊; 所以poll() 函數(shù)的功能和返回值的含義與 select() 函數(shù)的功能和返回值的含義是完全一樣的,兩者之間的差別就是內(nèi)部實(shí)現(xiàn)方式不一樣,select()函數(shù)基本上可以在所有支持文件描述符操作的系統(tǒng)平臺上運(yùn) 行(如:Linux 、Unix 、Windows、MacOS等),可移植性好,而poll()函數(shù)則只有個(gè)別的的操作系統(tǒng)提供支持(如:SunOS、Solaris、AIX、HP提供 支持,但是Linux不提供支持),可移植性差; strust pollfd結(jié)構(gòu)說明: typedef struct pollfd { int fd; /* 需要被檢測或選擇的文件描述符*/ short events; /* 對文件描述符fd上感興趣的事件 */ short revents; /* 文件描述符fd上當(dāng)前實(shí)際發(fā)生的事件*/ } pollfd_t; typedef unsigned long nfds_t; 經(jīng)常檢測的事件標(biāo)記: POLLIN/POLLRDNORM(可讀)、POLLOUT/POLLWRNORM(可寫)、POLLERR(出錯(cuò)) 如果是對一個(gè)描述符上的多個(gè)事件感興趣的話,可以把這些常量標(biāo)記之間進(jìn)行按位或運(yùn)算就可以了; 比如:對socket描述符fd上的讀、寫、異常事件感興趣,就可以這樣做:struct pollfd fds; fds[nIndex].events=POLLIN | POLLOUT | POLLERR; 當(dāng) poll()函數(shù)返回時(shí),要判斷所檢測的socket描述符上發(fā)生的事件,可以這樣做: struct pollfd fds; 檢測可讀TCP連接請求: if((fds[nIndex].revents & POLLIN) == POLLIN){//接收數(shù)據(jù)/調(diào)用accept()接收連接請求} 檢測可寫: if((fds[nIndex].revents & POLLOUT) == POLLOUT){//發(fā)送數(shù)據(jù)} 檢測異常: if((fds[nIndex].revents & POLLERR) == POLLERR){//異常處理} poll函數(shù)可用的測試值 注意:后三個(gè)只能作為描述字的返回結(jié)果存 儲(chǔ)在revents中,而不能作為測試條件用于events中。 第二個(gè)參數(shù)nfds是用來指定數(shù)組fdarray的長度。 最后一個(gè)參數(shù)timeout是指定poll函數(shù)返回前等待多長時(shí)間。 它的取值如下:
一個(gè)使用poll的網(wǎng)絡(luò)程序例子: 文章出處:飛諾網(wǎng)(www.):http://dev./course/6_s ... 0100326/201427.html #include <fcntl.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <errno.h> #include <poll.h> #define MAX_BUFFER_SIZE 1024 /* 緩沖區(qū)大小*/ #define IN_FILES 3 /* 多路復(fù)用輸入文件數(shù)目*/ #define TIME_DELAY 6000 /* 超時(shí)時(shí)間秒數(shù) */ #define MAX(a, b) ((a > b)?(a) ![]() int main(void) { struct pollfd fds[IN_FILES]; char buf[MAX_BUFFER_SIZE]; int i, res, real_read, maxfd; /*首先按一定的權(quán)限打開兩個(gè)源文件*/ fds[0].fd = 0; if((fds[1].fd = open ("in1", O_RDONLY|O_NONBLOCK)) < 0) { printf("Open in1 error\n" ![]() return 1; } if((fds[2].fd = open ("in2", O_RDONLY|O_NONBLOCK)) < 0) { printf("Open in2 error\n" ![]() return 1; } /*取出兩個(gè)文件描述符中的較大者*/ for (i = 0; i < IN_FILES; i++) { fds.events = POLLIN; } while(fds[0].events || fds[1].events || fds[2].events) { if (poll(fds, IN_FILES, TIME_DELAY) <= 0) { printf(" ![]() ![]() return 1; } for (i = 0; i< IN_FILES; i++) { if (fds.revents) { memset(buf, 0, MAX_BUFFER_SIZE); real_read = read(fds.fd, buf, MAX_BUFFER_SIZE); if (real_read < 0) { if (errno != EAGAIN) { return 1; } } else if (!real_read) { close(fds.fd); fds.events = 0; } else { if (i == 0) { if ((buf[0] == 'q') || (buf[0] == 'Q')) { return 1; } } else { buf[real_read] = '\0'; printf("%s", buf); } } /* end of if real_read*/ } /* end of if revents */ } /* end of for */ } /*end of while */ exit(0); } |
|