epoll网络编程示例
epoll
是一种在 Linux 上可用的高性能 I/O 事件通知机制,用于处理大量并发连接。
以下是使用 epoll 进行网络编程的基本步骤:
1. 创建 epoll 实例:使用 epoll_create 函数创建一个 epoll 实例。
2. 添加监听的文件描述符:使用 epoll_ctl 函数将需要监听的文件描述符添加到 epoll 实例中,并指定感兴趣的事件。
3. 等待事件发生:使用 epoll_wait 函数等待事件发生。该函数会阻塞直到有事件发生,或者超时。
4. 处理事件:当 epoll_wait 返回时,根据返回的事件列表,处理发生的事件。
下面是一个简单的 C++ 实现示例,展示如何使用 epoll
进行网络编程:
#include <iostream>
#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// EPOLL 相关常量
const int EPOLL_SIZE = 1024;
const int EPOLL_TIMEOUT = 1000; // 毫秒
// 定义一个结构体表示 EPOLL 事件
struct epoll_event {
uint32_t events; // 发生的事件
void* data; // 数据指针
};
// 创建 EPOLL 句柄
int createEpoll() {
int epollFd = epoll_create(EPOLL_SIZE);
if (epollFd == -1) {
std::cerr << "Failed to create epoll." << std::endl;
exit(EXIT_FAILURE);
}
return epollFd;
}
// 添加 EPOLL 事件到 EPOLL 句柄中
void addEpollEvent(int epollFd, int fd, uint32_t events) {
struct epoll_event event;
event.events = events;
event.data.fd = fd;
if (epoll_ctl(epollFd, EPOLL_CTL_ADD, fd, &event) == -1) {
std::cerr << "Failed to add epoll event." << std::endl;
exit(EXIT_FAILURE);
}
}
// 修改 EPOLL 事件
void modifyEpollEvent(int epollFd, int fd, uint32_t events) {
struct epoll_event event;
event.events = events;
event.data.fd = fd;
if (epoll_ctl(epollFd, EPOLL_CTL_MOD, fd, &event) == -1) {
std::cerr << "Failed to modify epoll event." << std::endl;
exit(EXIT_FAILURE);
}
}
// 删除 EPOLL 事件
void removeEpollEvent(int epollFd, int fd) {
if (epoll_ctl(epollFd, EPOLL_CTL_DEL, fd, nullptr) == -1) {
std::cerr << "Failed to remove epoll event." << std::endl;
exit(EXIT_FAILURE);
}
}
// 等待 EPOLL 事件发生
int waitEpollEvents(int epollFd, struct epoll_event* events, int numEvents, int timeout) {
int numReady = epoll_wait(epollFd, events, numEvents, timeout);
if (numReady == -1) {
std::cerr << "Failed to wait epoll events." << std::endl;
exit(EXIT_FAILURE);
}
return numReady;
}
// 处理 EPOLL 事件
void handleEpollEvent(struct epoll_event* event) {
int fd = event->data.fd;
uint32_t events = event->events;
if (events & EPOLLIN) { // 输入事件
std::cout << "EPOLLIN event on fd " << fd << std::endl;
}
if (events & EPOLLOUT) { // 输出事件
std::cout << "EPOLLOUT event on fd " << fd << std::endl;
}
}
int main() {
int serverFd, newSocket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[1024] = {0};
int epollFd = createEpoll();
// 创建一个 TCP 服务器 socket
serverFd = socket(AF_INET, SOCK_STREAM, 0);
if (serverFd == -1) {
std::cerr << "Failed to create socket." << std::endl;
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
// 将 socket 绑定到指定的端口
if (bind(serverFd, (struct sockaddr *)&address, sizeof(address)) == -1) {
std::cerr << "Failed to bind socket." << std::endl;
exit(EXIT_FAILURE);
}
// 开始监听连接
if (listen(serverFd, 1) == -1) {
std::cerr << "Failed to listen on socket." << std::endl;
exit(EXIT_FAILURE);
}
addEpollEvent(epollFd, serverFd, EPOLLIN);
while (1) {
int numEvents = waitEpollEvents(epollFd, events, EPOLL_SIZE, EPOLL_TIMEOUT);
for (int i = 0; i < numEvents; i++) {
handleEpollEvent(&events[i]);
}
// 接受新连接
if (newSocket = accept(serverFd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) {
addEpollEvent(epollFd, newSocket, EPOLLIN);
std::cout << "New connection established with client." << std::endl;
}
}
close(epollFd);
close(serverFd);
return 0;
}
这个示例中创建了一个 epoll
句柄,并使用 epoll
来监听服务器的 socket。通过添加、修改和删除事件,以及等待事件发生来处理输入和输出事件。
Do not communicate by sharing memory; instead, share memory by communicating.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)