IO多路複用之poll

不同於select使用三個位圖來表示三個fdset的方式,poll使用一個pollfd的指針實現。

wKiom1eM2F_w1k7hAADN9AWMhB0400.png    pollfd結構包含了要監視的event和發生的event,不再使用select“參數-值”傳遞的方式。同時,pollfd並沒有最大數量限制(但是數量過大後性能也是會下降)。和select函數一樣,poll返回後,需要輪詢pollfd來獲取就緒的描述符。

    從上面看,select和poll都需要在返回後,通過遍歷文件描述符來獲取已經就緒的socket。事實上,同時連接的大量客戶端在一時刻可能只有很少的處於就緒狀態,因此隨着監視的描述符數量的增長,其效率也會線性下降。

代碼描述:

server.c

  1 #include<stdio.h>                                                           
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<poll.h>
  5 #include<time.h>
  6 #include<unistd.h>
  7 #include<sys/types.h>
  8 #include<sys/socket.h>
  9 #include<netinet/in.h>
 10 #include<arpa/inet.h>
 11 
 12 #define _BACKLOG_ 5
 13 #define _SIZE_ 1024
 14 
 15 void Usage(const char* proc)
 16 {
 17     printf("%s [ip][port]\n",proc);
 18 }
 19 
 20 int Start_sock(char* _ip,int _port)
 21 {
 22     int sock=socket(AF_INET,SOCK_STREAM,0);
 23     if(sock<0)
 24     {
 25         perror("socket");
 26         exit(1);
 27     }
 28     struct sockaddr_in local;
 29     local.sin_family=AF_INET;
 30     local.sin_port=htons(_port);
 31     local.sin_addr.s_addr=inet_addr(_ip);
 32     socklen_t len=sizeof(local); 
 33     if(bind(sock,(struct sockaddr*)&local,len)<0)
 34     {
 35         perror("bind");
 36         exit(2);
 37     }
 38     if(listen(sock,_BACKLOG_)<0)
 39     {
 40         perror("listen");
 41         exit(3);
 42     }
 43     return sock;
 44 }
 45 int main(int argc,char* argv[])
 46 {
 47     if(argc!=3)
 48     {
 49         Usage(argv[0]);
 50     }
 51     char* ip=argv[1];
 52     int port=atoi(argv[2]);  
 53     int listen_sock=Start_sock(ip,port);
 54     
 55     struct sockaddr_in cli;
 56     socklen_t len=sizeof(cli);
 57 
 58     struct pollfd _pfd[_SIZE_];
 59     _pfd[0].fd=listen_sock;
 60     _pfd[0].events=POLLIN;
 61     _pfd[0].revents=0;
 62 
 63     int i=0;
 64     for(i=1;i<_SIZE_;++i)
 65     {
 66         _pfd[i].fd=-1;
 67         _pfd[i].events=POLLIN;
 68         _pfd[i].revents=0;
 69     }
 70     int done=0;
 71     int timeout=5000;
 72     int max=1;
 73     while(!done)
 74     {
 75         switch(poll(_pfd,max,timeout))
 76         {
 77             case 0: //timeout    
 78             {
 79                 printf("timeout...\n");
 80                 break;
 81             }
 82             case -1: //errno
 83             {
 84                 perror("poll");
 85                 break;
 86             }
 87             default:
 88             {
 89                 for(i=0;i<_SIZE_;++i)
 90                 {
 91                     if(_pfd[i].fd==listen_sock&&_pfd[i].revents & POLLIN)
 92                     {
 93                         int new_sock=accept(_pfd[i].fd,(struct sockaddr*)&cl    i,&len);
 94                         if(new_sock<0)
 95                         {
 96                             perror("accept");
 97                             continue;
 98                         }
 99                         int j=0;
100                         for(j=0;j<_SIZE_;++j)     
101                         {
102                             if(_pfd[j].fd<0)
103                             {
104                                 _pfd[j].fd=new_sock;
105                                 _pfd[j].events=POLLIN;
106                                 _pfd[j].revents=0;
107                                 break;
108                             }
109                         }
110                         if(j==_SIZE_)
111                         {
112                             printf("full");
113                             close(new_sock);
114                         }
115                         max++;
116                         printf("get a new connect:%d\n",new_sock);
117                     }
118                     else if(_pfd[i].fd>0&&_pfd[i].revents & POLLIN)
119                     {
120                         char buf[1024];
121                         memset(buf,'\0',sizeof(buf));
122                         ssize_t _s=read(_pfd[i].fd,buf,sizeof(buf)-1);
123                         if(_s<0)
124                         {         
125                             perror("read");
126                             close(_pfd[i].fd);
127                         }
128                         else if(_s==0)
129                         {
130                             printf(" client close...\n");
131                             close(_pfd[i].fd);
132                         }
133                         else
134                         {
135                             buf[_s]='\0';
136                             printf("client say:%s",buf);
137                             write(_pfd[i].fd,buf,sizeof(buf)-1);
138                             fflush(stdout);
139                         }
140                     }
141                     else
142                     {}
143                 }
144                 break;
145             }
146 
147         }
148     }
149     return 0;
150 }

client.c

  1 #include<stdio.h>                                                           
  2 #include<stdlib.h>
  3 #include<string.h>
  4 #include<unistd.h>
  5 #include<sys/types.h>
  6 #include<sys/socket.h>
  7 #include<netinet/in.h>
  8 #include<arpa/inet.h>
  9 
 10 void Usage(const char* proc)
 11 {
 12     printf("%s [ip][port]\n",proc);
 13 }
 14 
 15 int main(int argc,char* argv[])
 16 {
 17     if(argc!=3)
 18     {
 19         Usage(argv[0]);
 20         exit(1);
 21     }
 22     char* ip=argv[1];
 23     int port=atoi(argv[2]);
 24     int client_sock=socket(AF_INET,SOCK_STREAM,0);
 25     if(client_sock<0)
 26     {
 27         perror("socket");
 28         exit(2);
 29     }
 30     struct sockaddr_in remote;
 31     remote.sin_family=AF_INET;
 32     remote.sin_port=htons(port);
 33     remote.sin_addr.s_addr=inet_addr(ip);
 34 
 35     if(connect(client_sock,(struct sockaddr*)&remote,sizeof(remote))<0)
 36     {
 37         perror("connect");
 38         exit(3);
 39     }
 40     char buf[1024];
 41     while(1)
 42     {
 43         memset(buf,'\0',sizeof(buf));
 44         printf("please input:");
 45         fflush(stdout);
 46         fgets(buf,sizeof(buf)-1,stdin);
 47         ssize_t _s=write(client_sock,buf,sizeof(buf)-1);
 48         if(_s<0)
 49         {
 50             perror("write");
 51             exit(4);
 52         }    
 53         _s=read(client_sock,buf,sizeof(buf)-1);
 54         if(_s<0)
 55         {
 56             perror("read");
 57             exit(5);
 58         }
 59         else if(_s==0)
 60         {
 61             close(client_sock);
 62         }
 63         else
 64         {
 65             buf[_s]='\0';
 66             printf("server->client:%s",buf);
 67             fflush(stdout);
 68         }
 69     }
 70     return 0;
 71 }

執行結果:

wKiom1eM3JygcAC9AAB0eIVHC1s852.png


wKioL1eM3RXB_p5rAABsCNajnX0298.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章