# io多路复用之select详解
一、前备知识1、io多路复用在一个线程中实现服务器与多个客户端之间的链接与信息的收发2、select系统调用select函数属于系统调用每次调用都会把fd_set在用户态和内核态之间来回copy所以select效率不如epoll3、select使用selectmaxfd1rfdswfdserrfdsstruct timeval *timeout参数1maxfd1fd从0到maxfd有maxfd1个需要遍历maxfd1次参数2、3、4rfds可读文件描述符集合的首地址用来往可读集合中写入fd。由于一般用只一个rfds即可实现多个客户端数据的收发所以经常只创建一个rfds来记录所有可读的cfd参数5阻塞等待的超时时间如果填NULL表示永久等待如果想要设置时间需要定义一个如下结构体类型的变量并将地址传递进去structtimeval{longtv_sec;/* 秒数 */longtv_usec;/* 微秒 */};andstructtimespec{longtv_sec;/* 秒数 */longtv_nsec;/* 纳秒 */};4、返回值0:成功返回解除本次阻塞的文件描述符的个数0:表示设置的超时时间时间已经到达但是没有事件事件产生-1表示失败置位错误码二、代码详解fd_set rfds,rset;//rfds用于存储所有的cfd来收发消息rset存储所有fd中有io的fd来检测sockfd有没有listen到新的客户端连接FD_ZERO(rfds);//清空防止脏读FD_SET(sockfd,rfds);//将sockfd添加到rfds中intmaxfdsockfd;//目前最大的文件描述符时sockfdwhile(1){rsetrfds;intnreadyselect(maxfd1,rset,NULL,NULL,NULL);//阻塞等待0~maxfd中出现io有io就代表 sockfd收到了新的客户端连接请求 或 有客户端fd发来了消息。并返回有io的fd的数量if(FD_ISSET(sockfd,rset)){// accept如果sockfd在rset中说明有sockfd收到了新的客户端连接请求intclientfdaccept(sockfd,(structsockaddr*)clientaddr,len);printf(accept finshed: %d\n,clientfd);FD_SET(clientfd,rfds);// 将cfd添加到rfdsif(clientfdmaxfd)maxfdclientfd;//更新maxfd}// recvinti0;for(isockfd1;imaxfd;i){// i fdif(FD_ISSET(i,rset)){charbuffer[1024]{0};intcountrecv(i,buffer,1024,0);if(count0){// disconnectprintf(client disconnect: %d\n,i);close(i);FD_CLR(i,rfds);continue;}printf(RECV: %s\n,buffer);countsend(i,buffer,count,0);printf(SEND: %d\n,count);}}}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2448784.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!