UNIX网络编程 poll函数

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描述字不是一个打开的文件

前四个标识符处理输入,紧接的三个表示符处理输出。而最后的三个表示符处理错误。而最后的三个常量值不能在events中设置,当相应的条件存在时就在revents中返回。


第二个参数:

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;
                }
            }
        }
    }
}


版权声明:本文为wrx1721267632原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。