http://blog.csdn.net/li_ning_/article/details/52167224
poll
一、poll()函数:
这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,自认为poll和select大同小异,下面是这个函数的声明:
- #include <poll.h>
-
- int poll(struct pollfd *fds, nfds_t nfds, int timeout);
参数:
1.第一个参数:一个结构数组,struct pollfd:
fds:是一个struct pollfd结构类型的数组,每个数组元素都是一个pollfd结构,用于指定测试某个给定描述字fd的条件。存放需要检测其状态的Socket描述符;每当调用这个函数之后,系统不会清空这个数组,操作起来比较方便;特别是对于socket连接比较多的情况下,在一定程度上可以提高处理的效率;这一点与select()函数不同,调用select()函数之后,select()函数会清空它所检测的socket描述符集合,导致每次调用select()之前都必须把socket描述符重新加入到待检测的集合中;因此,select()函数适合于只检测一个socket描述符的情况,而poll()函数适合于大量socket描述符的情况;
结构如下:
- struct pollfd{
- int fd;
- short events;
- short revents;
- };
events和revents是通过对代表各种事件的标志进行逻辑或运算构建而成的。events包括要监视的事件(就是我需要关注的时间,是读?是写?还是出错?),poll用已经发生的事件填充revents。poll函数通过在revents中设置标志肌肤POLLHUP、POLLERR和POLLNVAL来反映相关条件的存在。不需要在events中对于这些标志符相关的比特位进行设置。如果fd小于0, 则events字段被忽略,而revents被置为0.标准中没有说明如何处理文件结束。文件结束可以通过revents的标识符POLLHUN或返回0字节的常规读操作来传达。即使POLLIN或POLLRDNORM指出还有数据要读,POLLHUP也可能会被设置。因此,应该在错误检验之前处理正常的读操作。
poll函数的事件标志符值:
常量 | 说明 |
POLLIN | 普通或优先级带数据可读 |
POLLRDNORM | 普通数据可读 |
POLLRDBAND | 优先级带数据可读 |
POLLPRI | 高优先级数据可读 |
POLLOUT | 普通数据可写 |
POLLWRNORM | 普通数据可写 |
POLLWRBAND | 优先级带数据可写 |
POLLERR | 发生错误 |
POLLHUP | 发生挂起 |
POLLNVAL | 描述字不是一个打开的文件 |
注意:
1)后三个只能作为描述字的返回结果存储在revents中,而不能作为测试条件用于events中。
2)第二个参数nfds:要监视的描述符的数目。
3)最后一个参数timeout:是一个用毫秒表示的时间,是指定poll在返回前没有接收事件时应该等待的时间。如果 它的值为-1,poll就永远都不会超时。如果整数值为32个比特,那么最大的超时周期大约是30分钟。
timeout值 | 说明 |
INFTIM | 永远等待 |
0 | 立即返回,不阻塞进程 |
>0 | 等待指定数目的毫秒数 |
如果是对一个描述符上的多个事件感兴趣的话,可以把这些常量标记之间进行按位或运算就可以了;
比如:
对socket描述符fd上的读、写、异常事件感兴趣,就可以这样做:
- struct pollfd fds;
-
- fds[index].events=POLLIN | POLLOUT | POLLERR;
当 poll()函数返回时,要判断所检测的socket描述符上发生的事件,可以这样做:
- struct pollfd fds;
-
-
- if((fds[nIndex].revents & POLLIN) == POLLIN)
- {
- <span style="white-space:pre"> </span>
- }
-
-
- if((fds[nIndex].revents & POLLOUT) == POLLOUT)
- {
- <span style="white-space:pre"> </span>
- }
-
-
- if((fds[nIndex].revents & POLLERR) == POLLERR)
- {
- <span style="white-space:pre"> </span>
- }
二、实例TCP服务器的服务器程序
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <netinet/in.h>
- #include <netdb.h>
- #include <string.h>
- #include <errno.h>
- #include <poll.h> //for poll
-
- #define LISTENQ 1024
- #define MAXLINE 1024
- #define OPEN_MAX 50000
-
- #ifndef INFTIM
- #define INFTIM -1
- #endif
-
- int start_up(char* ip,int port)
- {
-
-
- int sock=socket(AF_INET,SOCK_STREAM,0);
- if(sock<0)
- {
- perror("sock");
- exit(0);
- }
-
-
- struct sockaddr_in local;
- local.sin_port=htons(port);
- local.sin_family=AF_INET;
- local.sin_addr.s_addr=inet_addr(ip);
-
-
- if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
- {
- perror("bind");
- exit(1);
- }
-
- if(listen(sock,back_log)<0)
- {
- perror("sock");
- exit(1);
- }
- return sock;
- }
-
- int main(int argc, char *argv[])
- {
- int i, maxi, connfd, sockfd;
- int nready;
- ssize_t n;
- socklen_t clilen;
-
- struct sockaddr_in servaddr;
- socklen_t len=sizeof(servaddr);
-
- char buf[BUFSIZ];
- struct pollfd client[OPEN_MAX];
- if( argc != 3 )
- {
- printf("Please input %s <hostname>\n", argv[0]);
- exit(2);
- }
-
- int listenfd=start_up(argv[1],argv[2]);
-
- client[0].fd = listenfd;
- client[0].events = POLLIN;
- client[0].revents = 0;
-
- for(i = 1;i < OPEN_MAX; ++i)
- {
- client[i].fd = -1;
- }
-
- maxi = 0;
- while(1)
- {
- nready = poll(client, maxi+1,INFTIM);
- if( client[0].revents & POLLIN)
- {
- connfd = accept(listenfd,(struct sockaddr*)&servaddr, &clilen);
-
- for(i = 1; i < OPEN_MAX; ++i)
- {
- if( client[i].fd < 0 )
- {
- client[i].fd = connfd;
- client[i].events = POLLIN;
- break;
- }
- if( i == OPEN_MAX )
- {
- printf("too many clients");
- exit(1);
- }
-
- if( i > maxi )
- maxi = i;
-
- if( --nready <= 0 )
- continue;
- }
- }
-
- for(i = 1; i <= maxi; i++)
- {
- if( (sockfd = client[i].fd) < 0)
- continue;
-
- if(client[i].revents & (POLLIN | POLLERR))
- {
- if( (n = read(sockfd, buf, MAXLINE)) < 0)
- {
- if( errno == ECONNRESET)
- {
- close(sockfd);
- client[i].fd = -1;
- }
- else
- perror("read error");
- }
- else if(n == 0)
- {
- close(sockfd);
- client[i].fd = -1;
- }
- else
- write(sockfd, buf, n);
- if(--nready <= 0)
- break;
- }
- }
- }
- exit(0);
- }
赐教!