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)
{