poll

来源:互联网 发布:凌鹏软件 编辑:程序博客网 时间:2024/05/18 14:13

  poll提供的功能与select类似,不过在处理流设备时,它能够提供额外的信息。

#include <poll.h>  int poll(struct pollfd fd[], nfds_t nfds, int timeout);

poll与select不同,select用三个文件描述符集,pollfd结构包含了要监视的event和发⽣生的event,不再使⽤用select“参数-值”传递的⽅方式。同时,pollfd并没有最⼤大数量限制(但是数量过⼤大后性能也是会下降)。 和select函数⼀一样,poll返回后,需要轮询pollfd数组来获取就绪的描述符。poll将返回的事件放在结构体的revents中。
简单的poll服务器:

#include <stdio.h>#include <unistd.h>#include <poll.h>#include <arpa/inet.h>#include <stdlib.h>#include <netinet/in.h>#include <sys/types.h>#include <sys/socket.h>void usage(const char* proc){    printf("usage: %s [local_ip] [port]\n",proc);}int startup(const char* ip,int port){    //pfd.fd = client_sock;    int sock = socket(AF_INET,SOCK_STREAM,0);    if(sock < 0)    {        perror("socket");        exit(1);    }    struct sockaddr_in sd;    sd.sin_family = AF_INET;    sd.sin_port = htons(port);    sd.sin_addr.s_addr = inet_addr(ip);    //int socks;    if(bind(sock,(struct sockaddr*)&sd,sizeof(sd)) < 0)    {        perror("bind");        exit(2);    }    if(listen(sock,5) < 0)    {        perror("listen");        exit(3);    }    return sock;}int main(int argc,char* argv[]){    if(argc != 3) {        usage(argv[0]);        exit(0);    }    struct pollfd pfd[100];    int i = 0;    int max = 0;    for(;i<100; i++)    {        pfd[i].fd = -1;    }    int client_sock = startup(argv[1],atoi(argv[2]));    while(1)    {        pfd[0].fd = client_sock;        pfd[0].events = POLLIN;        max++;        int x = poll(pfd,max,-1);        if(x > 0)        {            i=0;            if(((pfd[0].revents & pfd[0].events) == 1) && pfd[0].fd == client_sock)            {                    struct sockaddr_in peer;                    socklen_t len =sizeof(peer);                    int client = accept(client_sock,(struct sockaddr*)&peer,&len);                    printf("get a new client\n");                    for(;i<100;i++)                    {                        if(pfd[i].fd < 0)                        {                            pfd[i].fd = client;                            pfd[i].events = POLLIN;                            break;                        }                    }             }             for(i=1;i<max;i++)                {                    if((pfd[i].revents & pfd[i].events) == 1)                    {                        //printf("a\n");                        char buf[1024];                        int new_fd = pfd[i].fd;                        int s;                        s = read(new_fd,buf,sizeof(buf));                        if(s < 0)                        {                            printf("client exit!\n");                            close(new_fd);                        }                        buf[s]=0;                        printf("client : %s\n",buf);                    }                }//for        }//        else        {            perror("poll");            exit(6);        }    }    return 0;}

poll的优点:
1)poll() 不要求开发者计算最大文件描述符加一的大小。
2)poll() 在应付大数目的文件描述符的时候相比于select速度更快
3)它没有最大连接数的限制,原因是它是基于链表来存储的。
poll的缺点:
1)大量的fd的数组被整体复制于用户态和内核地址空间之间,而不管这样的复制是不是有意义。
2)与select一样,poll返回后,需要轮询pollfd来获取就绪的描述符。