epoll模型主要有2种工作方式:水平触发(LT)和边缘触发(ET),本文主要是关于边缘触发的。本文实现的epoll多线程模型主要是,主线程等待事件触发,然后把相关事件放入队列,线程池从队列中取出数据处理事件。
下面是具体实现:
#include <stdarg.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <sys/sendfile.h>
#include <dirent.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <resolv.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <string.h>
#include <string>
#include <iostream>
#include "ThreadPool.h"
using namespace std;
static string strIP="192.168.0.168";
static int nPort=8088;
static string strDir="/home/temp/http_server";
const int MAX_EVENT=10;
struct epoll_event ev, events[MAX_EVENT];
int epfd;
enum {NeedRead_Event,Reading_Event,Error_Req,NeedWrite_Event,Writing_Event};
struct Task
{
epoll_event m_oEvent;
string m_strFilePath;
int m_nCurSize;
int m_nType;
int m_nReadOrWritefd;
int m_nFileLen;
int m_nSockfd;
};
char* dir_up(char *Path)
{
int len;
len = strlen(Path);
if (len > 1 && Path[len - 1] == '/')
{
len--;
}
while (Path[len - 1] != '/' && len > 1)
{
len--;
}
Path[len] = 0;
return Path;
}
char *strsplit(char **s,char del)
{
char *d, *tok;
if (!s || !*s)
return NULL;
tok = *s;
d = strchr(tok, del);
if (d) {
*d = '\0';
*s = d + 1;
} else
*s = NULL;
return tok;
}
char* urldecode( char* encd, char* decd)
{
int j,i;
char *cd = encd;
char p[2];
unsigned int num;
j=0;
for( i = 0; i < strlen(cd); i++ )
{
memset( p, '\0', 2 );
if( cd[i] != '%' )
{
decd[j++] = cd[i];
continue;
}
p[0] = cd[++i];
p[1] = cd[++i];
p[0] = p[0] - 48 - ((p[0] >= 'A') ? 7 : 0) - ((p[0] >= 'a') ? 32 : 0);
p[1] = p[1] - 48 - ((p[1] >= 'A') ? 7 : 0) - ((p[1] >= 'a') ? 32 : 0);
decd[j++] = (p[0] * 16 + p[1]);
}
decd[j] = '\0';
return decd;
}
void *ReadTask(void *arg)
{
Task *pTask=(Task*)arg;
char *cBuffer=new char[128*1024];
if(pTask->m_nType==NeedRead_Event)
{
int nSize=read(pTask->m_nSockfd,cBuffer,128*1024);
if(nSize==0)
{
close(pTask->m_nSockfd);
epoll_ctl(epfd, EPOLL_CTL_DEL,pTask->m_nSockfd, &(pTask->m_oEvent));
delete pTask;
return NULL;
}
else if(nSize<0)
{
cout<<errno<<endl;
if (errno == EINTR)
{
pTask->m_oEvent.events = EPOLLIN | EPOLLET | EPOLLONESHOT;
epoll_ctl(epfd, EPOLL_CTL_MOD,pTask->m_nSockfd, &(pTask->m_oEvent));
return NULL;
}
if (errno == EAGAIN)
{
return NULL;
}
}
else
{
char *cMethon=strsplit(&cBuffer,' ');
if(cBuffer==NULL)
{
pTask->m_nType=E