IO复用使程序可以同时监视多个文件描述符,提高性能。
需要指出的是, I/O 复用虽然能同时监听多个文件描述符,但它本身是阻塞的。并且当
多个文件描述符同时就绪时,如果不采取额外的措施,程序就只能按顺序依处理其中的每一
个文件描述符,这使得服务器看起来好像是串行工作的。如果要提高并发处理的能力,可以
配合使用多线程或多进程等编程方法。
select的原理图:
首先将文件描述符放到文件描述符集合当中,select去检测是否有事件发生,调用select产生返回值,返回值大于0代表有事件发生,去处理该事件,在处理事件时也可能加入新的文件描述符。返回0代表时间超时,返回-1代表失败。
select函数:
int select(int maxfd, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
maxfd 参数指定的被监听的文件描述符的总数。它通常被设置为 select 监听的所有文件描述符中的最大值+1,readfds、 writefds 和 exceptfds 参数分别指向可读、可写和异常等事件对应的文件
描述符集合。
下面给出部分代码:
int main() {int sockfd = InitSocket();assert(sockfd != -1);fd_set readfds;int fds[MAX_FD];InitFds(fds, MAX_FD);AddFdToFds(fds, sockfd, MAX_FD);while (1) {int maxfd = SetFdToFdset(&readfds, fds, MAX_FD);struct timeval timeout;timeout.tv_sec = 2; // 秒数timeout.tv_usec = 0; // 微秒数int n = select(maxfd + 1, &readfds, NULL, NULL, &timeout);if (n < 0) {printf("select error\n");break;} else if (n == 0)printf("time out\n");continue;}DealReadyEvent(fds, MAX_FD, &readfds, sockfd);
}exit(0);
}