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 }
阅读全文
0 0
- i/o多路转接 select(一)
- I/O的多路转接: select
- I/O多路转接----select调用
- I/O多路转接之select
- I/O多路转接之select
- I/O多路转接之select
- I/O多路转接之select
- I/O多路转接之select
- I/O多路转接之select
- 【Linux】I/O多路转接select
- I/O多路转接之select
- I/O多路转接之select
- I/O多路转接之--select
- I/O多路转接之select
- I/O多路转接----select
- I/O多路转接之select
- I/O多路转接之select
- I/O多路转接(一)——select函数
- 数据库初级入门
- Win10下Appium环境部署
- 浅谈gulp前端工程化
- 陌生的NSUserDefaults
- java菜鸟 socket简易局域网聊天室
- i/o多路转接 select(一)
- 怎么监听某篇帖子的访问量
- [YTU]_2433( C++习题 对象数组求最大值)
- STL vector用法介绍
- 设计模式---原型模式
- 设计模式学习
- 图像的上采样(up-sampling)和下采样(down-sampling)
- extjs xtype类型
- Mysql数据库备份的问题:mysqldump: Got error: 1049: Unknown database ‘blog;’ when selecting the database