poll提供的功能于select类似,不过在处理流设备的时候,它能提供额外的信息.
#include<poll.h>
int poll(struct pollfd *fdarray, unsigned long nfds, int timeout);
第一个参数:
struct pollfd {
int fd; //文件描述符
short events; //请求的事件
short revevts; //返回的事件
};
这个参数就类似于select中间的三个参数一般,不过该参数中revents成员返回该描述符的状态。就避免使用值—结果参数。
poll函数的事件标志符值:
常量 | 说明 |
POLLIN | 普通或优先级带数据可读 |
POLLRDNORM | 普通数据可读 |
POLLRDBAND | 优先级带数据可读 |
POLLPRI | 高优先级数据可读 |
POLLOUT | 普通数据可写 |
POLLWRNORM | 普通数据可写 |
POLLWRBAND | 优先级带数据可写 |
POLLERR | 发生错误 |
POLLHUP | 发生挂起 |
POLLNVAL | 描述字不是一个打开的文件 |
第二个参数:
nfds参数是要监视的描述符的数目。
第三个参数:
timeout参数指定poll函数等待的事件。
timeout值 说明
INFTIM 永远等待
0 立即返回,不阻塞进程
>0 等待指定数目的毫秒数
INFTIM常被定义为一个负值。若果系统不能提供毫秒级精度的定时器,该值就向上舍入到最接近的支持值。
#define MAXLINE 100
#define LISTENQ 12
int main()
{
int i, maxi, listenfd, connfd, sockfd;
int nready;
ssize_t n;
char buf[MAXLINE];
socklen_t clilen;
struct pollfd client[OPEN_MAX];
struct sockaddr_in cliaddr, servaddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = 5375;
bind(listenfd, (struct sockaddr*) &servaddr, sizeof(servaddr));
listen(listenfd, LISTENQ);
client[0].fd = listenfd;
client[0].events = POLLRDNORM;
for (i = 1; i < OPEN_MAX; i++)
{
client[i].fd = -1;
}
maxi = 0;
for ( ; ; )
{
nready = poll(client, maxi + 1, INFTIM);
if (client[0].revents & POLLRDNORM)
{
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
for (i = 1; i < OPEN_MAX; i++)
{
if (client[i].fd < 0)
{
client[i].fd = connfd;
break;
}
if (i == OPEN_MAX)
{
err_quit("too many clients");
}
client[i].events = POLLRDNORM;
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 & (POLLRDNORM | POLLERR))
{
if ( (n = read(sockfd, buf, MAXLINE)) < 0 )
{
if (errno == ECONNRESET)
{
close(sockfd);
client[i].fd = -1;
}
else
{
err_sys("read error");
}
}
else if (n == 0)
{
close(sockfd);
client[i].fd = -1;
}
else
{
write(sockfd, buf, n);
}
if (--nready <= 0)
{
break;
}
}
}
}
}