吴中网站开发建设多少钱,茂名网站建设哪家好,律师 wordpress,建立淘宝客网站一、select引入 一次 I/O 分为两个部分#xff1a;1#xff09;等待数据就绪 2#xff09;进行数据转移 1、select 原理#xff1a; select的原理就是减少等待数据就绪的比重#xff0c;巧妙的利用等待队列机制让用户进程适当在没有资源可读/写时睡眠#xff0c;有资…一、select引入 一次 I/O 分为两个部分1等待数据就绪 2进行数据转移 1、select 原理 select的原理就是减少等待数据就绪的比重巧妙的利用等待队列机制让用户进程适当在没有资源可读/写时睡眠有资源可读/写时唤醒。下面我们看 看select睡眠的详细过程。 select会循环遍历它所监测的fd_set一组文件描述符(fd)的集合内的所有文件描述符对应的驱动程序的poll函数。驱动程序提供的poll函数首先会将 调用select的用户进程插入到该设备驱动对应资源的等待队列(如读/写等待队列)然后返回一个bitmask告诉select当前资源哪些可用。当select循环遍历完 所有fd_set内指定的文件描述符对应的poll函数后如果没有一个资源可用(即没有一个文件可供操作)则select让该进程睡眠一直等到有资源可用为止 进程被唤醒(或者timeout)继续往下执行。 select:系统提供select函数来实现多路复用输入/输出模型。select系统调用是⽤用来让我们的程序监视多个文件句柄的状态变化的。 程序会停在select这里等待直到被监视的文件句柄有一个或多个发生了状态改变。 句柄 0是标准输⼊入1是标准输出2是标准错误输出。0、1、2是整数表⽰示的对应的FILE * 结构的表⽰示就是stdin、stdout、stderr。 2、select 参数 nfds是需要监视的最大的⽂文件描述符值1 rdset需要检测的可读⽂文件描述符的集合 wrset可写⽂文件描述符的集合 exset异常⽂文件描述符的集合。 struct timeval结构⽤用于描述⼀一段时间长度如果在这个时间内需要监视的描述符没有事件发生则函数返回返回值为0。 下⾯面的宏提供了处理这三种描述词组的⽅方式: FD_CLR(inr fd,fd_set* set)⽤用来清除描述词组set中相关fd 的位 FD_ISSET(int fd,fd_set *set)⽤用来测试描述词组set中相关fd 的位是否为真 FD_SETint fd,fd_set*set⽤用来设置描述词组set中相关fd的位 FD_ZEROfd_set *set⽤用来清除描述词组set的全部位 参数timeout为结构timeval⽤用来设置select()的等待时间其结构定义如下 如果参数timeout设为 NULL则表示select没有timeoutselect将⼀一直被阻塞直到某个文件描述符上发生了事件。 0仅检测描述符集合的状态然后立即返回并不等待外部事件的发⽣生。 特定的时间值如果在指定的时间段里没有事件发生select将超时返回。 函数返回值 执行成功则返回⽂文件描述词状态已改变的个数 如果返回0代表在描述词状态改变前已超过timeout时间没有返回 当有错误发⽣生时则返回-1错误原因存于errno此时参数readfdswritefdsexceptfds和 timeout的值变成不可预测。错误值可能为 EBADF 文件描述词为无效的或该文件已关闭 EINTR 此调⽤用被信号所中断 EINVAL 参数n 为负值。 ENOMEM 核心内存不足 3、select模型的特点 1、可监控的⽂文件描述符个数取决与sizeof(fd_set)的值。我这边服务 器上sizeof(fd_set)512每bit表⽰示一个⽂文件描述符则我服务器上⽀支持的最大文件描述符是512*84096。 2、将fd加入select监控集的同时还要再使用一个数据结构array保存放到select监控集中的fd一是用于再select 返回后array作为源数据和fd_set进行FD_ISSET判断。二是select返回后会把以前加入的但并无事件发生的fd清空则每次开始 select前都要重新从array取得fd逐一加入FD_ZERO最先扫描array的同时取得fd最大值maxfd用于select的第一个 参数。 3、select模型必须在select前循环array加fd取maxfdselect返回后循环arrayFD_ISSET判断是否有时间发生。 4、select缺点 1每次调用select都需要把fd集合从用户态拷贝到内核态这个开销在fd很多时会很大 2同时每次调用select都需要在内核遍历传递进来的所有fd这个开销在fd很多时也很大 3select支持的文件描述符数量太小了默认是1024 5、select 服务器 #includestdio.h
#includestdlib.h
#includeunistd.h
#includesys/types.h
#includesys/socket.h
#includesys/select.h
#includearpa/inet.h
#includenetinet/in.h
#includestring.h
int array_fds[1024];
static void usage(char *proc)
{printf(usage:%s [local_ip] [local_port]\n,proc);
}
int startup(char* _ip,int _port)
{//create socketint socksocket(AF_INET,SOCK_STREAM,0);if(sock0){perror(socket);return 2;}//port multiplexingint flg1; setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,flg,sizeof(flg));struct sockaddr_in local;local.sin_familyAF_INET;local.sin_addr.s_addrinet_addr(_ip);local.sin_porthtons(_port);//bindif(bind(sock,(struct sockaddr*)local,sizeof(local))0){perror(bind);return 3;}//listenif(listen(sock,10)0){perror(listen);return 4;}return sock;
}
int main(int argc,char *argv[])
{if(argc!3){usage(argv[0]);return 1;}int listen_sockstartup(argv[1],atoi(argv[2]));int maxfd0;fd_set rfds;int array_sizesizeof(array_fds)/sizeof(array_fds[0]);array_fds[0]listen_sock;int i1;for(;iarray_size;i){array_fds[i]-1;}while(1){struct timeval _timeout{0,0};FD_ZERO(rfds);maxfd-1;for(i0;iarray_size;i){if(array_fds[i]0){FD_SET(array_fds[i],rfds);if(array_fds[i]maxfd){maxfdarray_fds[i];}}}switch(select(maxfd1,rfds,NULL,NULL,_timeout)){case 0:printf(timeout...\n);break;case -1:perror(select\n);break;default:{int j0;for(;jarray_size;j){if(array_fds[j]0){continue;}if(j0 FD_ISSET(array_fds[j],rfds)){struct sockaddr_in client;socklen_t lensizeof(client);int new_fdaccept(array_fds[j],\(struct sockaddr*)client,len);if(new_fd0){perror(accept);continue;}else{printf(get a new client:(%s %d)\n,\inet_ntoa(client.sin_addr),\ntohs(client.sin_port));int k1;for(;karray_size;k){if(array_fds[k]0){array_fds[k]new_fd;break;}}if(karray_size){close(new_fd);}}}else if(j!0 FD_ISSET(array_fds[j],rfds)){char buf[10240];ssize_t sread(array_fds[j],buf,sizeof(buf)-1);if(s0){buf[s]0;printf(client say:%s\n,buf);}else if(s0){printf(client quit\n);close(array_fds[j]);array_fds[j]-1;}else{perror(read);close(array_fds[j]);array_fds[j]-1;}}}}break;}}return 0;
}