高级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淘汰掉了


分享标题:高级I/O---多路复用---poll
浏览路径:http://myzitong.com/article/pjpecp.html