基于epoll的聊天室程序

epoll作为高效的I/O多路复用模型,相比poll和select具有优势。主要难点在于理解水平触发和边沿触发的区别。边沿触发只在状态变化时触发,如从不可读到可读,而水平触发则在可读状态下持续触发。在使用边沿触发时,需要确保处理完所有数据,避免重复触发。本文通过一个简单的练习例子,展示了epoll在聊天室程序中的应用,客户端代码采用QT编写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                epoll相对于poll和select这两个多路复用的I/O模型更加的高效。epoll的函数很简单,麻烦的地方在于水平出发和边沿触发。

               用张图来说明下

             

ET(边沿)只是在状态反转时触发,比如从不可读到可读。而LT(水平)就是如果可读,就会一直触发。所以在使用ET的时候要做一些额外的处理,比如可读的,一直把缓冲区读完,进入不可读状态,下次来数据才会触发。

下面贴出代码,只是一个简单的练习的例子

#ifndef SOCKETHEADS_H
#define SOCKETHEADS_H


#include <sys/types.h> 
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#endif //SOCKETHEADS_H


#ifndef EPOLL_H
#define EPOLL_H

#include <sys/epoll.h>
#include <unistd.h>


/**
 * @brief The Epoll class 对epoll的封装
 */
class Epoll
{
public:
    /**
     *
     */
    enum EPOLL_OP {ADD = EPOLL_CTL_ADD, MOD = EPOLL_CTL_MOD, DEL = EPOLL_CTL_DEL};
    /**
     * 最大的连接数和最大的回传事件数
     */
    Epoll(int _max = 30, int maxevents = 20);
    ~Epoll();
    int create();
    int add(int fd, epoll_event *event);
    int mod(int fd, epoll_event *event);
    int del(int fd, epoll_event *event);
    void setTimeout(int timeout);
    void setMaxEvents(int maxevents);
    int wait();
    const epoll_event* events() const;
    const epoll_event& operator[](int index)
    {
        return backEvents[index];
    }
private:
    bool isValid() const;
    int max;
    int epoll_fd;
    int epoll_timeout;
    int epoll_maxevents;
    epoll_event *backEvents;
};




#endif //EPOLL_H

#include "zepoll.h"


Epoll::Epoll(int _max, int maxevents):max(_max),
    epoll_fd(-1),
    epoll_timeout(0),
    epoll_maxevents(maxevents),
    backEvents(0)
{

}

Epoll::~Epoll()
{
    if (isValid()) {
        close(epoll_fd);
    }
    delete[] backEvents;
}


inline
bool Epoll::isValid() const
{
    return epoll_fd > 0;
}

inline 
void Epoll::setTimeout(int timeout)
{
    epoll_timeout = timeout;
}

inline 
void Epoll::setMaxEvents(int maxevents)
{
    epoll_maxevents = maxevents;
}

inline
const epoll_event* Epoll::events() const
{
    return backEvents;
}



int Epoll::create()
{
    epoll_fd = ::epoll_create(max);
    if (isValid()) {
        backEvents = new epoll_event[epoll_maxevents];
    }
    return epoll_fd;
}

int Epoll::add(int fd, epoll_event *event)
{
### 使用Epoll实现聊天室 在Linux环境下,`epoll` 是一种高效的 I/O 多路复用机制,适用于处理大量并发连接。通过 `epoll` 实现聊天室可以高效管理多个客户端连接并及时响应数据传输请求。 #### 创建服务器端代码结构 为了创建基于 `epoll` 的聊天室服务端程序,主要步骤包括初始化监听套接字、设置 `epoll` 文件描述符以及循环等待事件发生。以下是简化版的服务端框架: ```c #include <sys/epoll.h> #include <unistd.h> #include <stdio.h> #define MAX_EVENTS 10 int main() { int epoll_fd = epoll_create1(0); // 创建一个新的epoll实例[^1] struct epoll_event event; struct epoll_event *events; events = calloc(MAX_EVENTS, sizeof(event)); while (1) { int n_fds = epoll_wait(epoll_fd, events, MAX_EVENTS, -1); for(int i=0; i<n_fds; ++i){ if(events[i].events & EPOLLIN){ /* handle read */ printf("Received data from fd %d\n", events[i].data.fd); } } } free(events); } ``` 这段代码展示了如何建立一个简单的 `epoll` 循环来监控文件描述符上的读就绪条件。实际应用中还需要加入更多的错误检查逻辑和服务功能开发。 #### 客户端接入与消息广播 当新的客户端尝试连接到聊天室时,服务器应该接受该连接并将新用户的文件描述符注册至 `epoll` 列表内以便后续监测其活动情况。每当检测到来自某个特定用户的数据输入,则需遍历所有已知在线成员并向他们转发这条信息完成群聊效果。 #### 错误处理和资源释放 考虑到网络通信过程中可能出现的各种异常状况,如断开连接等情形,在编写具体业务逻辑的同时也要充分考虑这些因素的影响,并采取适当措施加以应对,比如优雅关闭不再活跃的会话以防止内存泄漏等问题的发生。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值