12.IO多路复用:select—回射客户端服务器

1.select介绍

int select(int nfds, fd_set *restrict readfds,
   fd_set *restrict writefds, 
   fd_set *restrict errorfds,
   struct timeval *restrict timeout
 );
	成功:返回所有sets种的描述符个数:readfds+writefds+errorfds
	超时:返回0
	出错:返回-1
	
void FD_ZERO(fd_set *fdset);  //清空
void FD_CLR(int fd, fd_set *fdset);  //移出
void FD_SET(int fd, fd_set *fdset);  //放入
int FD_ISSET(int fd, fd_set *fdset); //判断fd是否在fdset中

select实现说明:
	调用select时,通过参数告诉内核(用户感兴趣的IO描述符)
	关心IO状态:输入,输出,错误
	调用者等待时间
	返回之后,内核告诉调用者多个描述符已经准备好了
	程序员判断哪些描述符发生变化
	调用返回后对准备好的描述符执行读写操作

案例一:回射客户端服务器模型

客户端代码:
	使用select监控两个文件描述字:stdin / clisock

#define ERR_EXIT(m) \                                                                                                                             
  do{ \                                                                                                                                           
    perror(m); \                                                                                                                                  
    exit(EXIT_FAILURE); \                                                                                                                         
  }while(0);                                                                                                                                      
                                                                                                                                                  
int main(){                                                                                                                                       
  int clisock=socket(AF_INET,SOCK_STREAM,0);                                                                                                      
  if(clisock==-1){                                                                                                                                
    perror("socket");                                                                                                                             
    exit(1);                                                                                                                                      
  }                                                                                                                                               
                                                                                                                                                  
  struct sockaddr_in svraddr;                                                                                                                     
  svraddr.sin_family=AF_INET;                                                                                                                     
  svraddr.sin_port=htons(8001);                                                                                                                   
  svraddr.sin_addr.s_addr=inet_addr("127.0.0.1");                                                                                                 
                                                                                                                                                  
  int ret=connect(clisock,(struct sockaddr*)&svraddr,sizeof(struct sockaddr));                                                                    
  if(ret<0)                                                                                                                                       
    ERR_EXIT("connect");                                                                                                                          
  printf("svraddr=%s,port=%d",inet_ntoa(svraddr.sin_addr),ntohs(svraddr.sin_port));                                                               
                                                                                                                                                  
  fd_set rset;                                                                                                                                    
  FD_ZERO(&rset);                                                                                                                                 

  int nready;
  int maxfd;
  int fd_stdin=fileno(stdin);  //int fileno(FILE *stream); 返回stream的整数形式的文件描述符                                                                                                                    
  maxfd=fd_stdin>clisock?fd_stdin:clisock;                                                                                                        
                                                                                                                                                  
  char sendbuf[1024]={0};                                                                                                                         
  char recvbuf[1024]={0};                                                                                                                         
  while(1){                                                                                                                                       
    FD_SET(fd_stdin,&rset);                                                                                                                       
    FD_SET(clisock,&rset);                                                                                                                        
                                                                                                                                                  
    nready=select(maxfd+1,&rset,NULL,NULL,NULL);                                                                                                  
    if(nready==-1){                                                                                                                               
      ERR_EXIT("select");                                                                                                                         
    }                                                                                                                                             
    else if(nready==0)                                                                                                                            
      continue;                                                                                                                                   
                                                                                                                                                  
    if(FD_ISSET(fd_stdin,&rset)){ //键盘输入                                                                                                                
      read(fd_stdin,sendbuf,sizeof(sendbuf));                                                                                                     
      write(clisock,sendbuf,sizeof(sendbuf));                                                                                                     
      memset(sendbuf,0,sizeof(sendbuf));                                                                                                          
    }                                                                                                                                             
    if(FD_ISSET(clisock,&rset)){ //closock文件描述符                                                                                                                  
      int ret=read(clisock,recvbuf,sizeof(recvbuf));                                                                                              
      if(ret<0){                                                                                                                                  
        ERR_EXIT("read");                                                                                                                         
      }                                                                                                                                           
      else if(ret==0){                                                                                                                            
        printf("peer close\n");                                                                                                                   
        break;                                                                                                                                    
      }                                                                                                                                           
      printf("      recv=%s",recvbuf);                                                                                                            
      memset(recvbuf,0,sizeof(recvbuf));                                                                                                          
    }                                                                                                                                             
  }                                                                                                                                                                                                                                                                                                
  return 0;                                                                                                                                       
}    

猜你喜欢

转载自blog.csdn.net/weixin_36750623/article/details/83242103