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

ET(边沿)只是在状态反转时触发,比如从不可读到可读。而LT(水平)就是如果可读,就会一直触发。所以在使用ET的时候要做一些额外的处理,比如可读的,一直把缓冲区读完,进入不可读状态,下次来数据才会触发。
下面贴出代码,只是一个简单的练习的例子
#ifndef SOCKETHEADS_H
#define SOCKETHEADS_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#endif //SOCKETHEADS_H
#ifndef EPOLL_H
#define EPOLL_H
#include
#include
/**
* @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)
{
if (isValid()) {
return ::epoll_ctl(epoll_fd, ADD, fd, event);
}
return -1;
}
int Epoll::mod(int fd, epoll_event *event)
{
if (isValid()) {
return ::epoll_ctl(epoll_fd, MOD, fd, event);
}
return -1;
}
int Epoll::del(int fd, epoll_event *event)
{
if (isValid()) {
return ::epoll_ctl(epoll_fd, DEL, fd, event);
}
return -1;
}
int Epoll::wait()
{
if (isValid()) {
return ::epoll_wait(epoll_fd, backEvents, epoll_maxevents, epoll_timeout);
}
return -1;
}
/********************************************************************
* author 周翔
* e-mail [email protected]
* blog http://blog.csdn.net/zhx6044
**********************************************************************/
#ifndef TASK_H
#define TASK_H
#include
#include
/**
* @brief The Task class 任务类
*/
class Task
{
public:
typedef enum {CONNECT = 0, DISCONNECT, TALKING} TASKFLAG;
Task(const std::string &message, TASKFLAG flag = TALKING);
const std::string& getMessage() const;
TASKFLAG getFlag() const;
void setIP(in_addr _ip);
int getS_fd() const;
void setS_fd(int _fd);
std::string getData() const;
private:
std::string m_message;
TASKFLAG m_flag;
in_addr ip;
int s_fd;
};
#endif // TASK_H
/********************************************************************
* author 周翔
* e-mail [email protected]
* blog http://blog.csdn.net/zhx6044
**********************************************************************/
#include "task.h"
Task::Task(const std::string &message, TASKFLAG flag):
m_message(message),
m_flag(flag)
{
}
const std::string& Task::getMessage() const
{
return m_message;
}
Task::TASKFLAG Task::getFlag() const
{
return m_flag;
}
void Task::setIP(in_addr _ip)
{
ip = _ip;
}
int Task::getS_fd() const
{
return s_fd;
}
void Task::setS_fd(int _fd)
{
s_fd = _fd;
}
std::string Task::getData() const
{
std::string re;
if (m_flag == CONNECT) {
re = ::inet_ntoa(ip) + std::string("----->") + "CONNECT! " + m_message;
} else {
if (m_flag == DISCONNECT) {
re = ::inet_ntoa(ip) + std::string("----->") + "DISCONNECT " + m_message;;
} else {
re = ::inet_ntoa(ip) + std::string("----->Talk:") + m_message;
}
}
return re;
}
#ifndef EPOLL_SERVER_H
#define EPOLL_SERVER_H
#include
客户端用qt简单的写了一个

需要客户端程序的在这里
http://pan.baidu.com/share/link?shareid=1711493932&uk=3507221172