#include "requestData.h"
#include "util.h"
#include "epoll.h"
#include <sys/epoll.h>
#include <unistd.h>
#include <sys/time.h>
#include <unordered_map>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <queue>
#include <cstdlib>
#include <opencv/cv.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace cv;
#include <iostream>
using namespace std;
pthread_mutex_t MutexLockGuard::lock=PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t MimeType::lock=PTHREAD_MUTEX_INITIALIZER;
std::unordered_map<std::string,std::string> MimeType::mime;
std::string MimeType::getMime(const std::string &suffix)
{
if (mime.size() == 0)
{
pthread_mutex_lock(&lock);
if (mime.size() == 0)
{
mime[".html"] = "text/html";
mime[".avi"] = "video/x-msvideo";
mime[".bmp"] = "image/bmp";
mime[".c"] = "text/plain";
mime[".doc"] = "application/msword";
mime[".gif"] = "image/gif";
mime[".gz"] = "application/x-gzip";
mime[".htm"] = "text/html";
mime[".ico"] = "application/x-ico";
mime[".jpg"] = "image/jpeg";
mime[".png"] = "image/png";
mime[".txt"] = "text/plain";
mime[".mp3"] = "audio/mp3";
mime["default"] = "text/html";
}
pthread_mutex_unlock(&lock);
}
if (mime.find(suffix) == mime.end())
return mime["default"];
else
return mime[suffix];
}
std::priority_queue<shared_ptr<mytimer>,std::deque<shared_ptr<mytimer>>,timerCmp> myTimerQueue;
requestData::requestData():
now_read_pos(0),
state(STATE_PARSE_URI),
h_state(h_start),
keep_alive(false),
againTimes(0)
{
cout << "requestData()" << endl;
}
requestData::requestData(int _epollfd, int _fd, std::string _path):
now_read_pos(0),
state(STATE_PARSE_URI),
h_state(h_start),
keep_alive(false),
againTimes(0),
path(_path),
fd(_fd),
epollfd(_epollfd)
{
cout << "requestData()" << endl;
}
requestData::~requestData()
{
cout << "~requestData()" << endl;
Epoll::epoll_del(fd,EPOLLIN | EPOLLET | EPOLLONESHOT);
if(timer.lock())
{
shared_ptr<mytimer> my_timer(timer.lock());
my_timer->clearReq();
timer.reset();
}
close(fd);
}
void requestData::addTimer(shared_ptr<mytimer> mtimer)
{
timer=mtimer;
}
int requestData::getFd()
{
return fd;
}
void requestData::setFd(int _fd)
{
fd = _fd;
}
void requestData::reset()
{
againTimes = 0;
content.clear();
file_name.clear();
path.clear();
now_read_pos = 0;
state = STATE_PARSE_URI;
h_state = h_start;
headers.clear();
keep_alive = false;
if(timer.lock())
{
shared_ptr<mytimer> my_timer(timer.lock());
my_timer->clearReq();
timer.reset();
}
}
void requestData::seperateTimer()
{
if (timer.lock())
{
shared_ptr<mytimer> my_timer(timer.lock());
my_timer->clearReq();
timer.reset();
}
}
void requestData::handleRequest()
{
char buff[MAX_BUFF];
bool isError = false;
while (true)
{
int read_num = readn(fd, buff, MAX_BUFF);
if (read_num < 0)
{
perror("1");
isError = true;
break;
}
else if (read_num == 0)
{
// 有请求出现但是读不到数据,可能是Request Aborted,或者来自网络的数据没有达到等原因
perror("read_num == 0");
if (errno == EAGAIN)
{
if (againTimes > AGAIN_MAX_TIMES)
isError = true;
else
++againTimes;
}
else if (errno != 0)
isError = true;
break;
}
string now_read(buff, buff + read_num);
content += now_read;
if (state == STATE_PARSE_URI)
{
int flag = this->parse_URI();
if (flag == PARSE_URI_AGAIN)
{
break;
}
else if (flag == PARSE_URI_ERROR)
{
perror("2");
isError = true;
break;
}
}
if (state == STATE_PARSE_HEADERS)
{
int flag = this->parse_Headers();
if (flag == PARSE_HEADER_AGAIN)
{
break;
}
else if (flag == PARSE_HEADER_ERROR)
{
perror("3");
isError = true;
break;
}
if(method == METHOD_POST)
{
state = STATE_RECV_BODY;
}
else
{
state = STATE_ANALYSIS;
}
}
if (state == STATE_RECV_BODY)
{
int content_length = -1;
if (headers.find("Content-length") != headers.end())
{
content_length = stoi(headers["Content-length"]);
}
else
{
isError = true;
break;
}
if (content.size() < content_length)
continue;
state = STATE_ANALYSIS;
}
if (state == STATE_ANALYSIS)
{
int flag = this->analysisRequest();
if (flag < 0)
{
isError = true;
break;
}
else if (flag == ANALYSIS_SUCCESS)
{
state = STATE_FINISH;
break;
}
else
{
isError = true;
break;
}
}
}
if (isError)
{
//delete this;
return;
}
// 加入epoll继续
if (state == STATE_FINISH)
{
if (keep_alive)
{
//printf("ok\n");
this->reset();
}
else
{
//delete this;
return;
}
}
shared_ptr<mytimer> mtimer(new mytimer(shared_from_this(),500)); //shared_from_this:返回this指针
this->addTimer(mtimer);
{
MutexLockGuard lock;
myTimerQueue.push(mtimer);
}
__uint32_t _epo_event= EPOLLIN | EPOLLET | EPOLLONESHOT;
int ret=Epoll::epoll_mod(fd,shared_from_this(),_epo_event);
if(ret<0)
{
return ;
}
}
int requestData::parse_URI()
{
string &str = content;
// 读到完整的请求行再开始解析请求
int pos = str.find('\r', now_read_pos);
if (pos < 0)
{
return PARSE_URI_AGAIN;
}
// 去掉请求行所占的空间,节省空间
string request_line = str.substr(0, pos);
if (str.size() > pos + 1)
str = str.substr(pos + 1);
else
str.clear();
// Method
pos = request_line.find("GET");
if (pos < 0)
{
pos = request_line.find("POST");
if (pos < 0)
{
return PARSE_URI_ERROR;
}
else
{
method = METHOD_POST;
}
}
else
{
method = METHOD_GET;
}
//printf("method = %d\n", method);
// filename
pos = request_line.find("/", pos);
if (pos < 0)
{
return PARSE_URI_ERROR;
}
else
{
int _pos = request_line.find(' ', pos);
if (_pos < 0)
return PARSE_URI_ERROR;
else
{
if (_pos - pos > 1)
{
file_name = request_line.substr(pos + 1, _pos - pos - 1);
int __pos = file_name.find('?');
if (__pos >= 0)
{
file_name = file_name.substr(0, __pos);
}
}
else
file_name = "index.html";
}
pos = _pos;
}
//cout << "file_nam
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
基于c++及linux网络编程的web服务器源码.zip 基于c++及linux网络编程的web服务器 该web服务器的主要内容如下: 使用了epoll边沿触发+EPOLLONESHOT+非阻塞IO 使用了一个固定线程数的线程池 实现了一个任务队列,由条件变量触发通知新任务的到来 实现了一个小根堆的定时器及时剔除超时请求,使用了STL的优先队列来管理定时器 解析了HTTP的get、post请求,支持长短连接 线程的工作分配为: 主线程负责等待epoll中的事件,并把到来的事件放进任务队列,在每次循环的结束剔除超时请求和被置为删除的时间结点 工作线程阻塞在条件变量的等待中,新任务到来后,某一工作线程会被唤醒,执行具体的IO操作和计算任务,如果需要继续监听,会添加到epoll中 锁的使用有两处: 第一处是任务队列的添加和取操作,都需要加锁,并配合条件变量,跨越了多个线程。 第二处是定时器结点的添加和删除,需要加锁,主线程和工作线程都要操作定时器队列。 几乎所有的指针采用智能指针 对于时间结点和HTTP类互指问题,采用weak_ptr解决
资源推荐
资源详情
资源评论
收起资源包目录
基于c++及linux网络编程的web服务器源码.zip (16个子文件)
WebServer
epoll.h 902B
requestData.cpp 17KB
Makefile 528B
util.h 184B
threadpool.cpp 3KB
main.cpp 3KB
config.h 14B
epoll.cpp 4KB
threadpool.h 2KB
favicon.ico 942B
requestData.h 3KB
index.html 13B
util.cpp 2KB
说明.md 1KB
images
1.png 52KB
2.png 67KB
共 16 条
- 1
资源评论
Make程序设计
- 粉丝: 5725
- 资源: 3570
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功