日期:2014-05-16  浏览次数:20750 次

apue unix环境编程中的传递文件描述符的使用不懂
loop(void)  
{  
 int i, n, maxfd, maxi, listenfd, clifd, nread;  
 char buf[MAXLINE];  
 uid_t uid;  
 fd_set rset, allset;  
 FD_ZERO(&allset);  
  /* obtain fd to listen for client requests on */  
 if ( (listenfd = serv_listen(CS_OPEN)) < 0)  
  log_sys("serv_listen error");  
 FD_SET(listenfd, &allset);  
 maxfd = listenfd;  
 maxi = -1;  
 for ( ; ; ) {  
  rset = allset; /* rset gets modified each time around */  
  if ( (n = select(maxfd + 1, &rset, NULL, NULL, NULL)) < 0) //为什么测试socket的表述符
  log_sys("select error");  
  if (FD_ISSET(listenfd, &rset)) {  
  /* accept new client request */  
  if ( (clifd = serv_accept(listenfd, &uid)) < 0)  
  log_sys("serv_accept error: %d", clifd);  
  i = client_add(clifd, uid);  
  FD_SET(clifd, &allset);  
  if (clifd > maxfd)  
  maxfd = clifd; /* max fd for select() */  
  if (i > maxi)  
  maxi = i; /* max index in client[] array */  
  log_msg("new connection: uid %d, fd %d", uid, clifd);  
  continue;  
  }  
  for (i = 0; i <= maxi; i++) { /* go through client[] array */  
  if ( (clifd = client[i].fd) < 0)  
  continue;  
  if (FD_ISSET(clifd, &rset)) {  
  /* read argument buffer from client */  
  if ( (nread = read(clifd, buf, MAXLINE)) < 0)  
  log_sys("read error on fd %d", clifd);  
  else if (nread == 0) {  
  log_msg("closed: uid %d, fd %d",  
  client[i].uid, clifd);  
  client_del(clifd); /* client has closed conn */  
  FD_CLR(clifd, &allset);  
  close(clifd);  
  } else /* process client's rquest */  
  request(buf, nread, clifd, client[i].uid);  
  }  
  }  
 }  
}




能不能解释一下其中select的作用;

------解决方案--------------------
select也可以用于socket描述符,和文件描述符一样。
------解决方案--------------------
select如果设置超时,可以用来做sleep()使用。

------解决方案--------------------
select 主要用来实现IO复用:可以在超时时间内同时监控3个IO集合的状态(读,写,错误),直到你设置的超时时间到达或者有io状态的变化,你要接受数据,那就是要关注读集合。


------解决方案--------------------
在程序中测试listenfd主要是为了不在accept处阻塞,以避免server端无法检测到client端的异常情况,而是在listenfd变得可读时,再去执行accept。