i/o多路转接 select(一)

来源:互联网 发布:wish加价如何优化 编辑:程序博客网 时间:2024/06/09 21:09

select 模型特点
1.可监控的文件描述符个数取决与文件描述符集的大小(sizeof(fd_set) 的值)。假设:sizeof ( fd_set) = 512, 每个bit表示一个文件描述符,则支持的最大文件描述符是512*8=4096.
2.将fd加入select监控集的同时,还要再使用一个数据结构array保存select监控集中的 fd_set,一是用于再select 返回后,array作为源数据和fd_set进行FD_ISSET判断。二是select返回后会把以前加入的但并无事件发生的fd清空,则每次开始 select前都要重新从array取得fd逐一加入(FD_ZERO最先),扫描array的同时取得fd最大值maxfd,用于select的第一个 参数。
3.可见select模型必须在select前循环array(加fd,取maxfd),select返回后循环array(FD_ISSET判断是否有时间发生)。

模型的缺点
1.每次进行select都要把文件描述符集fd由用户态拷贝到内核态,这样的开销会很大。
2 实现select服务器,内部要不断对文件描述符集fd进行循环遍历,当fd很多时,开销也很大。
3.select能监控文件描述符的数量有限,一般为1024。(sizeof(fd_set) * 8 = 1024(fd_set内部是以位图表示文件描述符)

select模型的服务器

  1 #include<stdio.h>                                                                                             2 #include<sys/types.h>  3 #include<netinet/in.h>  4 #include<arpa/inet.h>  5 #include<string.h>  6 #include<stdlib.h>  7 #include<time.h>  8 #include<unistd.h>  9  10 int array_fds[1024]; 11  12 int startup(char* ip,int port) 13 { 14     int sock = socket(AF_INET,SOCK_STREAM,0); 15     if(sock<0){ 16         perror("sock"); 17         exit(2); 18     } 19     int flg = 1; 20     setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&flg,sizeof(flg)); 21     struct sockaddr_in local; 22     local.sin_family = AF_INET; 23     local.sin_port = htons(port); 24     local.sin_addr.s_addr = inet_addr(ip); 25     if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0){ 26         perror("bind"); 27         exit(3); 28     } 29     if(listen(sock,10)){ 30         perror("listen"); 31         exit(4); 32     } 33     return sock; 34 } 35 int main(int argc,char*argv[]) 36 { 37     if(argc!=3){ 38         printf("Usage:%s [local_ip] [local_port]\n",argv[0]); 39         return 1; 40     } 41     int listen_sock = startup(argv[1],atoi(argv[2])); 42     int maxfds  = 0; //max fd_set  43     fd_set rfds;//fd_set 44     int array_size =  sizeof(array_fds)/sizeof(array_fds[0]); 45     array_fds[0] = listen_sock; 46       47     //init array_fds 48     int i = 1; 49     for(;i<array_size;i++){ 50         array_fds[i] = -1;                                                                      51     } 52  53     while(1) 54     { 55         struct timeval timeout = {0,0}; 56         FD_ZERO(&rfds); //empty 57         maxfds = -1; 58         i = 0; 59         for(;i<array_size;i++) 60         { 61             if(array_fds[i]>0){ 62                 FD_SET(array_fds[i],&rfds); //put array_fds[i] into rfds 63                 if(array_fds[i] > maxfds){ 64                     maxfds = array_fds[i]; 65                 } 66             } 67         } 68         switch(select(maxfds+1,&rfds,NULL,NULL,NULL)) 69         { 70             case 0: 71                 printf("timeout...\n"); 72                 break; 73             case -1: 74                 perror("select"); 75                 break;                76             default://success 77             { 78                 int j = 0; 79                 for(;j<array_size;++j) 80                 { 81                     if(array_fds[i]<0) 82                         continue; 83                     if(j==0&&FD_ISSET(array_fds[j],&rfds)) 84                     { 85                         struct sockaddr_in client; 86                         socklen_t len = sizeof(client); 87                         int new_fd = accept(array_fds[j],(struct sockaddr*)&client,&len); 88                         if(new_fd < 0){ 89                             perror("accept"); 90                             continue; 91                         } 92                         else{ 93                             printf("get a client:%s,%d\n",\ 94                                     inet_ntoa(client.sin_addr),\ 95                                     ntohs(client.sin_port)); 96                             int k = 1; 97                             for(;k<array_size;k++){ 98                                 if(array_fds[k] <0){ 99                                     array_fds[k] = new_fd;  101                                 }102                                 if( k == array_size){103                                     //no use file104                                     close(new_fd);105                                 }106                             }107                         }108                     }109                     else if(j!=0&&FD_ISSET(array_fds[j],&rfds))110                     {111                         char buf[1240];112                         ssize_t s = read(array_fds[j],\113                                 buf,sizeof(buf)-1);114                         if(s > 0){115                             buf[s]=0;116                             printf("client say#:%s\n",buf);117                         }118                         else if(s==0){119                             printf("client quit\n");120                             close(array_fds[j]);121                             array_fds[j]=-1;122                         }123                         else{124                             perror("read");125                             close(array_fds[j]);        126                         }127                     }128                 }129                 break;130             }131         }132     }133     return 0;134 }                                                                                           
原创粉丝点击