在C++网络编程中,处理多个客户端连接是一个常见需求。传统的阻塞式I/O模型在面对大量并发连接时效率低下。为了解决这个问题,操作系统提供了IO多路复用技术,而 poll 函数就是其中一种重要实现方式。本文将带你从零开始掌握 C++ 中 poll 函数的使用方法,即使你是编程小白也能轻松上手!

poll 是 Linux/Unix 系统提供的一个系统调用,用于监视多个文件描述符(file descriptor)的状态变化(如可读、可写、异常等),从而实现单线程同时处理多个 I/O 事件。它属于 IO多路复用 技术的一种,与 select 和 epoll 并列为三大经典方案。
相比 select,poll 没有文件描述符数量限制(FD_SETSIZE 限制),且接口更简洁,是学习高级网络编程的重要一步。
首先,我们需要包含头文件:
#include <poll.h>函数原型如下:
int poll(struct pollfd *fds, nfds_t nfds, int timeout);参数说明:
fds:指向 struct pollfd 数组的指针,每个元素描述一个要监视的文件描述符及其关注的事件。nfds:数组中元素的个数。timeout:超时时间(单位:毫秒)。-1 表示永久阻塞,0 表示立即返回(非阻塞),正数表示等待指定毫秒后超时。struct pollfd 的定义如下:
struct pollfd { int fd; // 要监视的文件描述符 short events; // 关注的事件(输入) short revents; // 实际发生的事件(输出)};| 事件常量 | 说明 |
|---|---|
POLLIN | 数据可读 |
POLLOUT | 可以写入数据 |
POLLERR | 发生错误 |
POLLHUP | 连接挂起(如对端关闭) |
下面是一个使用 poll 实现的简单回显服务器示例。它能同时处理多个客户端连接,当客户端发送消息时,服务器原样返回。
#include <iostream>#include <sys/socket.h>#include <netinet/in.h>#include <unistd.h>#include <poll.h>#include <cstring>#include <vector>#define MAX_CLIENTS 100#define BUFFER_SIZE 1024int main() { int server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd == -1) { std::cerr << "创建 socket 失败\n"; return -1; } int opt = 1; setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); struct sockaddr_in address; address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); if (bind(server_fd, (struct sockaddr*)&address, sizeof(address)) < 0) { std::cerr << "绑定失败\n"; close(server_fd); return -1; } listen(server_fd, 10); std::cout << "服务器启动,监听端口 8080...\n"; std::vector<struct pollfd> fds; struct pollfd server_pfd = {server_fd, POLLIN, 0}; fds.push_back(server_pfd); while (true) { int poll_count = poll(fds.data(), fds.size(), -1); if (poll_count == -1) { std::cerr << "poll 错误\n"; break; } // 检查是否有新连接 if (fds[0].revents & POLLIN) { int client_fd = accept(server_fd, nullptr, nullptr); if (client_fd != -1) { std::cout << "新客户端连接: " << client_fd << "\n"; struct pollfd client_pfd = {client_fd, POLLIN, 0}; fds.push_back(client_pfd); } } // 检查已有客户端是否有数据 for (size_t i = 1; i < fds.size(); ++i) { if (fds[i].revents & (POLLIN | POLLHUP | POLLERR)) { char buffer[BUFFER_SIZE]; ssize_t bytes = read(fds[i].fd, buffer, BUFFER_SIZE - 1); if (bytes <= 0) { // 客户端断开 std::cout << "客户端 " << fds[i].fd << " 断开连接\n"; close(fds[i].fd); fds.erase(fds.begin() + i); --i; // 调整索引 } else { buffer[bytes] = '\0'; std::cout << "收到消息: " << buffer << "\n"; write(fds[i].fd, buffer, bytes); // 回显 } } } } close(server_fd); return 0;}编译命令:
g++ -o server server.cpp运行后,你可以用 telnet localhost 8080 或其他 TCP 客户端测试。
优点:
缺点:
通过本文,你已经掌握了 C++ 中 poll 函数的基本用法、事件类型以及如何构建一个简单的多客户端服务器。作为 C++ poll函数 和 网络编程 的核心知识点,poll 是理解更高级 IO 多路复用机制(如 epoll)的基础。
虽然在现代高性能服务器中 epoll 更受欢迎,但 poll 依然因其简洁性和可移植性,在中小型项目和教学中广泛使用。希望这篇教程能帮助你迈出 IO多路复用 编程的第一步!
关键词回顾:C++ poll函数、网络编程、poll系统调用、IO多路复用
本文由主机测评网于2025-12-12发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://www.vpshk.cn/2025126461.html