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。通过添加、修改和删除事件,以及等待事件发生来处理输入和输出事件。

posted @   guanyubo  阅读(239)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示