千家信息网

高级I/O---多路复用---poll

发表于:2024-11-30 作者:千家信息网编辑
千家信息网最后更新 2024年11月30日,稍加改进的多路复用--pollpoll是一个在select上稍加改进的多路复用版本,不久后就被功能完善的epoll所取代,它与select的区别在于select的返回通过输入参数来返回,这样每次都要添
千家信息网最后更新 2024年11月30日高级I/O---多路复用---poll

稍加改进的多路复用--poll

poll是一个在select上稍加改进的多路复用版本,不久后就被功能完善的epoll所取代,它与select的区别在于select的返回通过输入参数来返回,这样每次都要添加要关心的文件描述符到其文件描述符集中,而poll设置了一个结构体指针参数,通过他就可以知道状态变化,但免不了的是依旧需要遍历整个buf,它的大小可以由用户自定义,但是过于大的集合会使得服务器负担大大加重,而太小的集合又因为大多的socket都在等待数据到来,效率上又会下滑很多,所以poll很尴尬。


poll的函数

 #include        int poll(struct pollfd *fds, nfds_t nfds, int timeout);                struct pollfd {               int   fd;         /* file descriptor */               short events;     /* requested events */               short revents;    /* returned events */           };

poll的函数与select不一样的地方就是它的fds参数,他是一个结构体指针,结构体的定义就是下面那个

struct pollfd,其中的events是设置的时候所要关心的时间,revents是输出当大于零的时候便说明发生了event所设置的情况,revents不用手动清空,他会自动清空。



因为和select差不多,就直接看代码吧

下面是实现的一个简单的poll版本的tcp服务器


因为前面的设置监听套接字和之前的都一样就忽略了

 43 void PollServer(int sock) 44 { 45     int i=0; 46     int max_fd=-1; 47     struct pollfd fds[_MAX_FDS_]; 48     for(;i<_MAX_FDS_;i++) 49     { 50         fds[i].fd=-1; 51     } 52     fds[0].fd=sock; 53     max_fd=sock; 54     fds[0].events=POLLIN; //设置为所关心的事件 55     int timeout; 56     while(1) 57     { 58         int new_sock=-1; 59  60         struct sockaddr_in client; 61         socklen_t client_len=sizeof(client); 62  63         fds[0].fd=sock; 64         fds[0].events=POLLIN; 65         timeout=5000; 66         switch(poll(fds,max_fd+1,timeout))//依然需要循环 67         { 68             case -1: 69                 perror("poll"); 70                 continue; 71             case 0: 72                 printf("timeout\n"); 73                 continue; 74             default: 75                 { 76                     for(i=0;i<_MAX_FDS_;i++) 77                     { 78                         int fd=fds[i].fd; 79                         if(fd==sock&&fds[i].revents>0)                                                                                         //当有新的连接时 80                         { 81                     new_sock=accept(sock,(struct sockaddr*)\ 82                                                                                                         &client,&client_len); 83                             printf("%d\n",new_sock); 84                             for(i=0;i<_MAX_FDS_;i++) 85                             { 86                                 if(fds[i].fd<0) 87                                 { 88                               fds[i].fd=new_sock; 89                               fds[i].events=POLLIN; 90                                     break; 91                                 } 92                             } 93                             if(i==_MAX_FDS_) 94                             { 95                                 close(new_sock); 96                             } 97                         } 98                         else if(fd>0&&fds[i].revents>0)                                                                                     //当有需要读的数据时 99                         {100                             char buf[1024];101                            memset(buf,'\0',sizeof(buf));102                      ssize_t size=read(fd,buf,sizeof(buf)-1);103                             if(size>0)104                             {105                                 buf[size]='\0';106                             printf("client::%s\n",buf);107                             }else if(size==0){108                                 close(fd);109                                 fds[i].fd=-1;110                                 fds[i].events=-1;111                             }else{112                                 perror("read");113                                 continue;114                             }115                         }116                     }117                 }118             }119         }120 }121


poll和select的区别并不大,所以很快被epoll淘汰掉了

0