首页 > 后端开发 > C++ > 正文

c++怎么操作IO多路复用select_c++ IO多路复用select方法

穿越時空
发布: 2025-10-07 12:32:02
原创
417人浏览过
C++中使用select实现IO多路复用,通过调用select()函数监控多个文件描述符的读写状态,结合fd_set宏操作管理集合,示例程序监听socket和标准输入,每次循环重置集合并调用select等待事件,支持超时机制,但存在性能瓶颈和fd数量限制,适用于小型或跨平台项目。

c++怎么操作io多路复用select_c++ io多路复用select方法

在C++中使用IO多路复用的 select 方法,主要是通过调用操作系统提供的 select() 系统函数来实现。它允许程序同时监控多个文件描述符(如socket、标准输入等),判断哪些已经准备好进行读、写或出现异常事件。这对于编写高性能网络服务器或需要处理多个并发连接的程序非常有用。

select 函数基本用法

select() 的函数原型定义在 <sys/select.h> 头文件中:

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

参数说明:

  • nfds:所有被监控的文件描述符中最大值加1(即从0到nfds-1)
  • readfds:监听可读事件的文件描述符集合
  • writefds:监听可写事件的文件描述符集合
  • exceptfds:监听异常事件的文件描述符集合
  • timeout:等待超时时间,可以设为阻塞(NULL)、非阻塞(tv_sec=0, tv_usec=0)或指定超时

fd_set 集合操作宏

select 使用 fd_set 类型来管理文件描述符集合,配合以下宏操作:

立即学习C++免费学习笔记(深入)”;

喵记多
喵记多

喵记多 - 自带助理的 AI 笔记

喵记多 27
查看详情 喵记多
  • FD_ZERO(fd_set *set):清空集合
  • FD_SET(int fd, fd_set *set):将文件描述符加入集合
  • FD_CLR(int fd, fd_set *set):从集合中移除文件描述符
  • FD_ISSET(int fd, fd_set *set):检查文件描述符是否在集合中(select 返回后使用)

C++ 示例:监听标准输入和 socket

下面是一个简单的 C++ 示例,演示如何使用 select 监听标准输入和一个 socket 连接:

#include <iostream>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <cstring>

int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};

// 创建 socket
server_fd = socket(AF_INET, SOCK_STREAM, 0);
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);

bind(server_fd, (struct sockaddr *)&address, sizeof(address));
listen(server_fd, 3);

std::cout << "等待连接...\n";
new_socket = accept(server_fd, (struct sockaddr*)&address, (socklen_t*)&addrlen);

fd_set readfds;
struct timeval timeout;

while (true) {
// 每次循环都要重新设置 fd_set
FD_ZERO(&readfds);
FD_SET(new_socket, &readfds);
FD_SET(STDIN_FILENO, &readfds); // 监听标准输入

int max_fd = (new_socket > STDIN_FILENO ? new_socket : STDIN_FILENO) + 1;

timeout.tv_sec = 5;
timeout.tv_usec = 0;

int activity = select(max_fd, &readfds, nullptr, nullptr, &timeout);

if (activity < 0) {
std::cerr << "select 错误\n";
break;
} else if (activity == 0) {
std::cout << "select 超时\n";
continue;
}

// 检查 socket 是否可读
if (FD_ISSET(new_socket, &readfds)) {
int valread = read(new_socket, buffer, 1024);
if (valread <= 0) {
std::cout << "客户端断开\n";
break;
}
std::cout << "收到数据: " << buffer << "\n";
memset(buffer, 0, 1024);
}

// 检查标准输入是否可读
if (FD_ISSET(STDIN_FILENO, &readfds)) {
std::string input;
std::getline(std::cin, input);
const char* msg = input.c_str();
send(new_socket, msg, strlen(msg), 0);
}
}

close(new_socket);
close(server_fd);
return 0;
}

注意事项与局限性

尽管 select 是跨平台兼容性较好的 IO 多路复用方式,但也有明显缺点:

  • 每次调用 select 都需要重新设置 fd_set 集合
  • 文件描述符数量受限(通常最多 1024)
  • 需要遍历所有监听的 fd 来检查状态变化,效率随 fd 数量增加而下降
  • 每次都要传递最大 fd + 1,开销较大

在 Linux 下,更推荐使用 pollepoll 实现更高性能的多路复用。

基本上就这些。select 虽然古老,但在小型项目或跨平台场景下仍很实用。

以上就是c++++怎么操作IO多路复用select_c++ IO多路复用select方法的详细内容,更多请关注php中文网其它相关文章!

c++速学教程(入门到精通)
c++速学教程(入门到精通)

c++怎么学习?c++怎么入门?c++在哪学?c++怎么学才快?不用担心,这里为大家提供了c++速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号