千家信息网

I/O多路转接   ----   poll

发表于:2024-11-11 作者:千家信息网编辑
千家信息网最后更新 2024年11月11日,一、pollpoll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多。二、poll相关函数#include i
千家信息网最后更新 2024年11月11日I/O多路转接   ----   poll

一、poll

poll的实现和select非常相似,只是描述fd集合的方式不同,poll使用pollfd结构而不是select的fd_set结构,其他的都差不多


二、poll相关函数

#include

int poll(struct pollfd *fds, nfds_t nfds, int timeout);

//fds: pollfd结构体

events: 要监视的事件

revents: 已经发生的事件, 设置标志 来反映相关条件的存在

常量 说明

POLLIN 普通或优先级带数据可读

POLLRDNORM 普通数据可读

POLLRDBAND 优先级带数据可读

POLLPRI 高优先级数据可读

POLLOUT 普通数据可写

POLLWRNORM 普通数据可写

POLLWRBAND 优先级带数据可写


// 只能作为描述字的返回结果存储在revents中

POLLERR 发生错误

POLLHUP 发生挂起

POLLNVAL 描述字不是一个打开的文件

struct pollfd {    int   fd;         /* 文件描述符 */      short events;     /* 请求的事件 */        short revents;    /* 返回的事件 */  };

//nfds: 要监视的描述符的数目

//timeout:指定poll在返回前没有接收事件时应该等待的时间【单位:ms】。

INFTIM: 永不超时

0 :立即返回

>0: 等待指定的时间

2、特点:

pollfd并没有最大数量限制(但是数量过大后性能也是会下降)。

和select函数一样,poll返回后,需要轮询pollfd来获取就绪的描述符。

select和poll都需要在返回后,通过遍历文件描述符来获取已经就绪的socket。事实上,同时连接的大量客户端在一时刻可能只有很少的处于就绪状态,因此随着监视的描述符数量的增长,其效率也会线性下降。

三、poll 服务器

#include #include#include#include#include#include#include#include#include#include#include#define _BACKLOG_ 5#define _MAX_NUM_ 64void usage(const char *proc){        printf("Usage: %s [ip][port]\n",proc);}static int startup(const char *ip,const int port){        int sock=socket(AF_INET,SOCK_STREAM,0);        if(sock < 0)        {                perror("socket");                exit(1);        }        int opt=1;        setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));        struct sockaddr_in local;        local.sin_family=AF_INET;        local.sin_port=htons(port);        local.sin_addr.s_addr=inet_addr(ip);                if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)        {                perror("bind");                exit(2);        }               if(listen(sock,_BACKLOG_) < 0)        {                perror("listen");                               exit(3);        }        return sock;}static int poll_server(int listen_sock){        struct sockaddr_in client;        socklen_t len=sizeof(client);                struct pollfd fds[_MAX_NUM_];        fds[0].fd=listen_sock;        fds[0].events=POLLIN;        fds[0].revents=0;        size_t i=0;        for(;i<_MAX_NUM_;++i)        {                fds[i].fd=-1;                fds[i].events=0;                fds[i].revents=0;        }        int max_fd=1;        int timeout=5000;        while(1)        {                switch(poll(fds,max_fd,timeout))                {                case -1://error                        perror("poll");                        break;                case 0://timeout                        printf("poll timeout");                        break;                default://normal                         {                                for(i=0;i<_MAX_NUM_;++i)                                {                                        //is listen events ready?                                        if(fds[i].fd == listen_sock && fds[i].revents == POLLIN)                                        {                                                int accept_sock=accept(listen_sock,(struct sockaddr*)&client,&len);                                                if(accept_sock < 0)                                                {                                                        perror("accept");                                                        continue;                                                }                                                printf("get a client...[ip: %s][port: %d]\n",\                                                                inet_ntoa(client.sin_addr),ntohs(client.sin_port));                                                for(i=0;i<_MAX_NUM_;++i)                                                {                                                        if(fds[i].fd == -1)                                                        {                                                                fds[i].fd=accept_sock;                                                                fds[i].events=POLLIN;                                                                max_fd++;                                                                break;                                                        }                                                }                                                if(i == _MAX_NUM_)                                                {                                                        close(accept_sock);                                                }                                        }                                        else if(fds[i].fd > 0 && fds[i].revents == POLLIN)                                        {                                                char buf[1024];                                                ssize_t _size=read(fds[i].fd,buf,sizeof(buf)-1);                                                if(_size > 0)//read success                                                {                                                        buf[_size]='\0';                                                        printf("Client # %s",buf);                                                }                                                else if(_size == 0)//client close                                                {                                                        printf("clint close...\n");                                                        struct pollfd tmp=fds[i];                                                        fds[i]=fds[max_fd-1];                                                        close(fds[max_fd-1].fd);                                                        fds[max_fd-1].fd=-1;                                                        fds[max_fd-1].events=0;                                                        fds[max_fd-1].revents=0;                                                        --max_fd;                                                }                                        }                                        else                                        {}                                }                        }                        break;                }        }        return 0;}int main(int argc,char *argv[]){        if(argc != 3)        {                usage(argv[0]);                return 1;        }        char *ip=argv[1];        int port=atoi(argv[2]);        int listen_sock=startup(ip,port);        poll_server(listen_sock);        close(listen_sock);        return 0;}

总结:

poll在返回后,需要通过遍历文件描述符来获取已经就绪的socket从而进行下一步操作;而且使用完监听套接字后,都需要进行关闭。


0