poll

本文详细介绍了poll函数的工作原理及其在服务器编程中的应用。对比select函数,poll提供了更好的性能和更大的灵活性,尤其是在处理大量文件描述符时更为高效。文章通过一个简单的poll服务器示例展示了如何使用poll进行事件监听。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  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来获取就绪的描述符。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值