高級I/O---多路複用---poll

稍加改進的多路複用--poll服務器

poll是一個在select上稍加改進的多路複用版本,不久後就被功能完善的epoll所取代,它與select的區別在於select的返回經過輸入參數來返回,這樣每次都要添加要關心的文件描述符到其文件描述符集中,而poll設置了一個結構體指針參數,經過他就能夠知道狀態變化,但免不了的是依舊須要遍歷整個buf,它的大小能夠由用戶自定義,可是過於大的集合會使得服務器負擔大大加劇,而過小的集合又由於大多的socket都在等待數據到來,效率上又會下滑不少,因此poll很尷尬。
socket


poll的函數tcp

 #include <poll.h>

       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參數,他是一個結構體指針,結構體的定義就是下面那個ide

struct pollfd,其中的events是設置的時候所要關心的時間,revents是輸出當大於零的時候便說明發生了event所設置的狀況,revents不用手動清空,他會自動清空。函數



由於和select差很少,就直接看代碼吧spa

下面是實現的一個簡單的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淘汰掉了ip

相關文章
相關標籤/搜索