IO Multiple
IO多路复用
系统调用函数,select, poll, epoll
select
select
函数是一个用于监视多个文件描述符的系统调用,常用于网络编程中以实现 I/O 多路复用。它允许程序在多个套接字上等待数据可读、可写或发生异常,而不需要为每个套接字单独使用阻塞调用。
select使用的原理 数据结构-位图
将要监视的事件的文件描述符
函数原型
#include <sys/select.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
void FD_ZERO(fd_set *set);//将set清空为0
void FD_SET(int fd, fd_set* set);//将fd设置到set集合中
void FD_CLR(int fd, fd_set* set);//将fd从set中清除出去
void FD_ISSET(int fd, fd_set* set);//判断fd是否在集合中
参数说明
- nfds: 监视的最大文件描述符加 1。通常是所有文件描述符中的最大值加 1。
- readfds: 指向
fd_set
结构的指针,表示哪些文件描述符需要检查是否可读。 - writefds: 指向
fd_set
结构的指针,表示哪些文件描述符需要检查是否可写。 - exceptfds: 指向
fd_set
结构的指针,表示哪些文件描述符需要检查是否发生异常。 - timeout: 指向
timeval
结构的指针,表示等待的最大时间。如果设置为NULL
,则会无限期等待;如果设置为零,则立即返回。
返回值
- 成功时返回活动文件描述符的数量;出错时返回 -1,并设置
errno
;如果超时返回 0。
fd_set readfds;
struct timeval timeout;
while (true) {
// 清空文件描述符集合
FD_ZERO(&readfds);
FD_SET(listen_sock, &readfds);
// 设置超时时间
timeout.tv_sec = 5; // 5 秒超时
timeout.tv_usec = 0;
// 调用 select
int activity = select(listen_sock + 1, &readfds, nullptr, nullptr, &timeout);
if (activity < 0) {
perror("select error");
break;
} else if (activity == 0) {
std::cout << "Timeout occurred, no incoming connections." << std::endl;
continue;
}
// 检查是否有新的连接,判断监听fd是否在readfd中
if (FD_ISSET(listen_sock, &readfds)) {
new_sock = accept(listen_sock, (struct