#include <sys/select.h> #include <sys/time.h>
// 返回值:如有就绪描述符,则返回就绪描述符数目;若超时则返回0,出错返回-1 int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset, const struct timeval *timeout);
#include <sys/select.h> #include <sys/time.h> void FD_SET(int fd, fd_set *fdset); // 设置文件描述符集fdset中对应于文件描述符fd的位(设置为1) void FD_CLR(int fd, fd_set *fdset); // 清除文件描述符集fdset中对应于文件描述符fd的位(设置为0) void FD_ISSET(int fd, fd_set *fdset); // 检测文件描述符集fdset中对应于文件描述符fd的位是否被设置 void FD_ZERO(fd_set *fdset); // 清除文件描述符集fdset中的全部位(既把全部位都设置为0
注意:服务器
在使用FD_ISSET测试fd_set数据类型中的描述符后,描述符集内任何与未就绪描述符对应函数
的位返回时均被清0,所以,每次从新调用select函数时,都须要将描述符集内所关心的位置为1测试
struct timeval{ long tv_sec; // 秒 long tv_usec; // 微秒 }
timeout参数的三种可能:
91 // 使用select的cli_io函数,使得在服务器进程终止后客户能够立刻获取通知 92 void cli_io_select(int sockfd, char *mark, FILE *fp) 93 { 94 int maxfdp1, n; 95 fd_set rset; 96 char sendline[MAXLINE], recvline[MAXLINE]; 97 98 FD_ZERO(&rset); 99 100 for ( ; ; ) 101 { 102 FD_SET(fileno(fp), &rset); 103 FD_SET(sockfd, &rset); 104 105 // fileno() 函数,将文件流指针转换为文件描述符· 106 maxfdp1 = max(fileno(fp), sockfd) + 1; 107 108 if (select(maxfdp1, &rset, NULL, NULL, NULL) < 0) 109 { 110 printf("Error select!\n"); 111 exit(1); 112 } 113 114 if (FD_ISSET(sockfd, &rset)) 115 { 116 if ( (n = read(sockfd, recvline, MAXLINE)) > 0 ) 117 { 118 recvline[n] = '\0'; 119 fputs(recvline, stdout); 120 } 121 } 122 123 if (FD_ISSET(fileno(fp), &rset)) 124 { 125 if (fgets(sendline, MAXLINE, fp) == NULL) 126 { 127 return; 128 } 129 130 if (write(sockfd, sendline, strlen(sendline)) < 0) 131 { 132 printf("Error write!\n"); 133 exit(1); 134 } 135 } 136 } 137 }