From a96a3c1f0ba8e6d973d1ea6ebcf5587549e3c5cc Mon Sep 17 00:00:00 2001 From: LinYa Date: Sat, 2 Nov 2019 11:04:05 +0800 Subject: [PATCH] Format in Google code style --- .clang-format | 2 + CMakeLists.txt | 4 +- WebServer/Channel.cpp | 75 +- WebServer/Channel.h | 188 ++--- WebServer/Epoll.cpp | 197 ++--- WebServer/Epoll.h | 52 +- WebServer/EventLoop.cpp | 212 +++-- WebServer/EventLoop.h | 104 ++- WebServer/EventLoopThread.cpp | 67 +- WebServer/EventLoopThread.h | 28 +- WebServer/EventLoopThreadPool.cpp | 55 +- WebServer/EventLoopThreadPool.h | 37 +- WebServer/HttpData.cpp | 1227 +++++++++++++---------------- WebServer/HttpData.h | 201 +++-- WebServer/Main.cpp | 85 +- WebServer/Server.cpp | 132 ++-- WebServer/Server.h | 40 +- WebServer/Timer.cpp | 113 ++- WebServer/Timer.h | 73 +- WebServer/Util.cpp | 425 +++++----- WebServer/base/AsyncLogging.cpp | 195 +++-- WebServer/base/AsyncLogging.h | 77 +- WebServer/base/Condition.h | 62 +- WebServer/base/CountDownLatch.cpp | 23 +- WebServer/base/CountDownLatch.h | 19 +- WebServer/base/CurrentThread.h | 50 +- WebServer/base/FileUtil.cpp | 51 +- WebServer/base/FileUtil.h | 26 +- WebServer/base/LogFile.cpp | 50 +- WebServer/base/LogFile.h | 36 +- WebServer/base/LogStream.cpp | 147 ++-- WebServer/base/LogStream.h | 187 ++--- WebServer/base/Logging.cpp | 2 +- WebServer/base/Logging.h | 50 +- WebServer/base/MutexLock.h | 68 +- WebServer/base/Thread.cpp | 183 ++--- WebServer/base/Thread.h | 50 +- WebServer/base/noncopyable.h | 16 +- WebServer/tests/HTTPClient.cpp | 405 +++++----- build.sh | 2 +- 40 files changed, 2253 insertions(+), 2763 deletions(-) create mode 100644 .clang-format diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..41e0670 --- /dev/null +++ b/.clang-format @@ -0,0 +1,2 @@ +Language: Cpp +BasedOnStyle: Google \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index d44e1d8..a7a88a8 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8) project(WebServer CXX) if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release") + set(CMAKE_BUILD_TYPE "Debug") endif() set(CXX_FLAGS @@ -17,7 +17,7 @@ set(CXX_FLAGS set(CMAKE_CXX_COMPILER "g++") set(CMAKE_CXX_FLAGS_DEBUG "-O0") -set(CMAKE_CXX_FLAGS_RELEASE "-O3") +set(CMAKE_CXX_FLAGS_RELEASE "-O0") string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") diff --git a/WebServer/Channel.cpp b/WebServer/Channel.cpp index 69381e1..dfda8ad 100755 --- a/WebServer/Channel.cpp +++ b/WebServer/Channel.cpp @@ -1,64 +1,47 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "Channel.h" -#include "Util.h" -#include "Epoll.h" -#include "EventLoop.h" + #include -#include #include #include + +#include + +#include "Epoll.h" +#include "EventLoop.h" +#include "Util.h" + using namespace std; -Channel::Channel(EventLoop *loop): - loop_(loop), - events_(0), - lastEvents_(0), - fd_(0) -{ } +Channel::Channel(EventLoop *loop) + : loop_(loop), events_(0), lastEvents_(0), fd_(0) {} -Channel::Channel(EventLoop *loop, int fd): - loop_(loop), - fd_(fd), - events_(0), - lastEvents_(0) -{ } +Channel::Channel(EventLoop *loop, int fd) + : loop_(loop), fd_(fd), events_(0), lastEvents_(0) {} -Channel::~Channel() -{ - //loop_->poller_->epoll_del(fd, events_); - //close(fd_); +Channel::~Channel() { + // loop_->poller_->epoll_del(fd, events_); + // close(fd_); } -int Channel::getFd() -{ - return fd_; -} -void Channel::setFd(int fd) -{ - fd_ = fd; -} +int Channel::getFd() { return fd_; } +void Channel::setFd(int fd) { fd_ = fd; } -void Channel::handleRead() -{ - if (readHandler_) - { - readHandler_(); - } +void Channel::handleRead() { + if (readHandler_) { + readHandler_(); + } } -void Channel::handleWrite() -{ - if (writeHandler_) - { - writeHandler_(); - } +void Channel::handleWrite() { + if (writeHandler_) { + writeHandler_(); + } } -void Channel::handleConn() -{ - if (connHandler_) - { - connHandler_(); - } +void Channel::handleConn() { + if (connHandler_) { + connHandler_(); + } } \ No newline at end of file diff --git a/WebServer/Channel.h b/WebServer/Channel.h index a3428a9..c48c77c 100755 --- a/WebServer/Channel.h +++ b/WebServer/Channel.h @@ -1,131 +1,97 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "Timer.h" -#include -#include -#include #include -#include #include - +#include +#include +#include +#include +#include "Timer.h" class EventLoop; class HttpData; - -class Channel -{ -private: - typedef std::function CallBack; - EventLoop *loop_; - int fd_; - __uint32_t events_; - __uint32_t revents_; - __uint32_t lastEvents_; - - // 方便找到上层持有该Channel的对象 - std::weak_ptr holder_; - -private: - int parse_URI(); - int parse_Headers(); - int analysisRequest(); - - CallBack readHandler_; - CallBack writeHandler_; - CallBack errorHandler_; - CallBack connHandler_; - -public: - Channel(EventLoop *loop); - Channel(EventLoop *loop, int fd); - ~Channel(); - int getFd(); - void setFd(int fd); - - void setHolder(std::shared_ptr holder) - { - holder_ = holder; - } - std::shared_ptr getHolder() - { - std::shared_ptr ret(holder_.lock()); - return ret; - } - - void setReadHandler(CallBack &&readHandler) - { - readHandler_ = readHandler; - } - void setWriteHandler(CallBack &&writeHandler) - { - writeHandler_ = writeHandler; +class Channel { + private: + typedef std::function CallBack; + EventLoop *loop_; + int fd_; + __uint32_t events_; + __uint32_t revents_; + __uint32_t lastEvents_; + + // 方便找到上层持有该Channel的对象 + std::weak_ptr holder_; + + private: + int parse_URI(); + int parse_Headers(); + int analysisRequest(); + + CallBack readHandler_; + CallBack writeHandler_; + CallBack errorHandler_; + CallBack connHandler_; + + public: + Channel(EventLoop *loop); + Channel(EventLoop *loop, int fd); + ~Channel(); + int getFd(); + void setFd(int fd); + + void setHolder(std::shared_ptr holder) { holder_ = holder; } + std::shared_ptr getHolder() { + std::shared_ptr ret(holder_.lock()); + return ret; + } + + void setReadHandler(CallBack &&readHandler) { readHandler_ = readHandler; } + void setWriteHandler(CallBack &&writeHandler) { + writeHandler_ = writeHandler; + } + void setErrorHandler(CallBack &&errorHandler) { + errorHandler_ = errorHandler; + } + void setConnHandler(CallBack &&connHandler) { connHandler_ = connHandler; } + + void handleEvents() { + events_ = 0; + if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)) { + events_ = 0; + return; } - void setErrorHandler(CallBack &&errorHandler) - { - errorHandler_ = errorHandler; + if (revents_ & EPOLLERR) { + if (errorHandler_) errorHandler_(); + events_ = 0; + return; } - void setConnHandler(CallBack &&connHandler) - { - connHandler_ = connHandler; + if (revents_ & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) { + handleRead(); } - - void handleEvents() - { - events_ = 0; - if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)) - { - events_ = 0; - return; - } - if (revents_ & EPOLLERR) - { - if (errorHandler_) errorHandler_(); - events_ = 0; - return; - } - if (revents_ & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) - { - handleRead(); - } - if (revents_ & EPOLLOUT) - { - handleWrite(); - } - handleConn(); + if (revents_ & EPOLLOUT) { + handleWrite(); } - void handleRead(); - void handleWrite(); - void handleError(int fd, int err_num, std::string short_msg); - void handleConn(); + handleConn(); + } + void handleRead(); + void handleWrite(); + void handleError(int fd, int err_num, std::string short_msg); + void handleConn(); - void setRevents(__uint32_t ev) - { - revents_ = ev; - } + void setRevents(__uint32_t ev) { revents_ = ev; } - void setEvents(__uint32_t ev) - { - events_ = ev; - } - __uint32_t& getEvents() - { - return events_; - } + void setEvents(__uint32_t ev) { events_ = ev; } + __uint32_t &getEvents() { return events_; } - bool EqualAndUpdateLastEvents() - { - bool ret = (lastEvents_ == events_); - lastEvents_ = events_; - return ret; - } - - __uint32_t getLastEvents() - { - return lastEvents_; - } + bool EqualAndUpdateLastEvents() { + bool ret = (lastEvents_ == events_); + lastEvents_ = events_; + return ret; + } + __uint32_t getLastEvents() { return lastEvents_; } }; typedef std::shared_ptr SP_Channel; \ No newline at end of file diff --git a/WebServer/Epoll.cpp b/WebServer/Epoll.cpp index 811629e..028bd1e 100755 --- a/WebServer/Epoll.cpp +++ b/WebServer/Epoll.cpp @@ -1,152 +1,121 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "Epoll.h" -#include "Util.h" -#include "base/Logging.h" -#include +#include #include -#include #include #include -#include +#include +#include #include -#include +#include +#include "Util.h" +#include "base/Logging.h" + #include #include using namespace std; - const int EVENTSNUM = 4096; const int EPOLLWAIT_TIME = 10000; typedef shared_ptr SP_Channel; -Epoll::Epoll(): - epollFd_(epoll_create1(EPOLL_CLOEXEC)), - events_(EVENTSNUM) -{ - assert(epollFd_ > 0); +Epoll::Epoll() : epollFd_(epoll_create1(EPOLL_CLOEXEC)), events_(EVENTSNUM) { + assert(epollFd_ > 0); } -Epoll::~Epoll() -{ } - +Epoll::~Epoll() {} // 注册新描述符 -void Epoll::epoll_add(SP_Channel request, int timeout) -{ - int fd = request->getFd(); - if (timeout > 0) - { - add_timer(request, timeout); - fd2http_[fd] = request->getHolder(); - } - struct epoll_event event; - event.data.fd = fd; - event.events = request->getEvents(); - - request->EqualAndUpdateLastEvents(); - - fd2chan_[fd] = request; - if(epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event) < 0) - { - perror("epoll_add error"); - fd2chan_[fd].reset(); - } +void Epoll::epoll_add(SP_Channel request, int timeout) { + int fd = request->getFd(); + if (timeout > 0) { + add_timer(request, timeout); + fd2http_[fd] = request->getHolder(); + } + struct epoll_event event; + event.data.fd = fd; + event.events = request->getEvents(); + + request->EqualAndUpdateLastEvents(); + + fd2chan_[fd] = request; + if (epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event) < 0) { + perror("epoll_add error"); + fd2chan_[fd].reset(); + } } - // 修改描述符状态 -void Epoll::epoll_mod(SP_Channel request, int timeout) -{ - if (timeout > 0) - add_timer(request, timeout); - int fd = request->getFd(); - if (!request->EqualAndUpdateLastEvents()) - { - struct epoll_event event; - event.data.fd = fd; - event.events = request->getEvents(); - if(epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &event) < 0) - { - perror("epoll_mod error"); - fd2chan_[fd].reset(); - } - } -} - - -// 从epoll中删除描述符 -void Epoll::epoll_del(SP_Channel request) -{ - int fd = request->getFd(); +void Epoll::epoll_mod(SP_Channel request, int timeout) { + if (timeout > 0) add_timer(request, timeout); + int fd = request->getFd(); + if (!request->EqualAndUpdateLastEvents()) { struct epoll_event event; event.data.fd = fd; - event.events = request->getLastEvents(); - //event.events = 0; - // request->EqualAndUpdateLastEvents() - if(epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, &event) < 0) - { - perror("epoll_del error"); + event.events = request->getEvents(); + if (epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &event) < 0) { + perror("epoll_mod error"); + fd2chan_[fd].reset(); } - fd2chan_[fd].reset(); - fd2http_[fd].reset(); + } } - - +// 从epoll中删除描述符 +void Epoll::epoll_del(SP_Channel request) { + int fd = request->getFd(); + struct epoll_event event; + event.data.fd = fd; + event.events = request->getLastEvents(); + // event.events = 0; + // request->EqualAndUpdateLastEvents() + if (epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, &event) < 0) { + perror("epoll_del error"); + } + fd2chan_[fd].reset(); + fd2http_[fd].reset(); +} // 返回活跃事件数 -std::vector Epoll::poll() -{ - while (true) - { - int event_count = epoll_wait(epollFd_, &*events_.begin(), events_.size(), EPOLLWAIT_TIME); - if (event_count < 0) - perror("epoll wait error"); - std::vector req_data = getEventsRequest(event_count); - if (req_data.size() > 0) - return req_data; - } +std::vector Epoll::poll() { + while (true) { + int event_count = + epoll_wait(epollFd_, &*events_.begin(), events_.size(), EPOLLWAIT_TIME); + if (event_count < 0) perror("epoll wait error"); + std::vector req_data = getEventsRequest(event_count); + if (req_data.size() > 0) return req_data; + } } -void Epoll::handleExpired() -{ - timerManager_.handleExpiredEvent(); -} +void Epoll::handleExpired() { timerManager_.handleExpiredEvent(); } // 分发处理函数 -std::vector Epoll::getEventsRequest(int events_num) -{ - std::vector req_data; - for(int i = 0; i < events_num; ++i) - { - // 获取有事件产生的描述符 - int fd = events_[i].data.fd; - - SP_Channel cur_req = fd2chan_[fd]; - - if (cur_req) - { - cur_req->setRevents(events_[i].events); - cur_req->setEvents(0); - // 加入线程池之前将Timer和request分离 - //cur_req->seperateTimer(); - req_data.push_back(cur_req); - } - else - { - LOG << "SP cur_req is invalid"; - } +std::vector Epoll::getEventsRequest(int events_num) { + std::vector req_data; + for (int i = 0; i < events_num; ++i) { + // 获取有事件产生的描述符 + int fd = events_[i].data.fd; + + SP_Channel cur_req = fd2chan_[fd]; + + if (cur_req) { + cur_req->setRevents(events_[i].events); + cur_req->setEvents(0); + // 加入线程池之前将Timer和request分离 + // cur_req->seperateTimer(); + req_data.push_back(cur_req); + } else { + LOG << "SP cur_req is invalid"; } - return req_data; + } + return req_data; } -void Epoll::add_timer(SP_Channel request_data, int timeout) -{ - shared_ptr t = request_data->getHolder(); - if (t) - timerManager_.addTimer(t, timeout); - else - LOG << "timer add fail"; +void Epoll::add_timer(SP_Channel request_data, int timeout) { + shared_ptr t = request_data->getHolder(); + if (t) + timerManager_.addTimer(t, timeout); + else + LOG << "timer add fail"; } \ No newline at end of file diff --git a/WebServer/Epoll.h b/WebServer/Epoll.h index ce77789..d42612a 100755 --- a/WebServer/Epoll.h +++ b/WebServer/Epoll.h @@ -1,35 +1,33 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once +#include +#include +#include +#include #include "Channel.h" #include "HttpData.h" #include "Timer.h" -#include -#include -#include -#include -class Epoll -{ -public: - Epoll(); - ~Epoll(); - void epoll_add(SP_Channel request, int timeout); - void epoll_mod(SP_Channel request, int timeout); - void epoll_del(SP_Channel request); - std::vector> poll(); - std::vector> getEventsRequest(int events_num); - void add_timer(std::shared_ptr request_data, int timeout); - int getEpollFd() - { - return epollFd_; - } - void handleExpired(); -private: - static const int MAXFDS = 100000; - int epollFd_; - std::vector events_; - std::shared_ptr fd2chan_[MAXFDS]; - std::shared_ptr fd2http_[MAXFDS]; - TimerManager timerManager_; + +class Epoll { + public: + Epoll(); + ~Epoll(); + void epoll_add(SP_Channel request, int timeout); + void epoll_mod(SP_Channel request, int timeout); + void epoll_del(SP_Channel request); + std::vector> poll(); + std::vector> getEventsRequest(int events_num); + void add_timer(std::shared_ptr request_data, int timeout); + int getEpollFd() { return epollFd_; } + void handleExpired(); + + private: + static const int MAXFDS = 100000; + int epollFd_; + std::vector events_; + std::shared_ptr fd2chan_[MAXFDS]; + std::shared_ptr fd2http_[MAXFDS]; + TimerManager timerManager_; }; \ No newline at end of file diff --git a/WebServer/EventLoop.cpp b/WebServer/EventLoop.cpp index 221afd9..a43d01e 100755 --- a/WebServer/EventLoop.cpp +++ b/WebServer/EventLoop.cpp @@ -1,150 +1,130 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "EventLoop.h" -#include "base/Logging.h" -#include "Util.h" -#include #include +#include #include +#include "Util.h" +#include "base/Logging.h" + using namespace std; __thread EventLoop* t_loopInThisThread = 0; -int createEventfd() -{ - int evtfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); - if (evtfd < 0) - { - LOG << "Failed in eventfd"; - abort(); - } - return evtfd; +int createEventfd() { + int evtfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); + if (evtfd < 0) { + LOG << "Failed in eventfd"; + abort(); + } + return evtfd; } EventLoop::EventLoop() -: looping_(false), - poller_(new Epoll()), - wakeupFd_(createEventfd()), - quit_(false), - eventHandling_(false), - callingPendingFunctors_(false), - threadId_(CurrentThread::tid()), - pwakeupChannel_(new Channel(this, wakeupFd_)) -{ - if (t_loopInThisThread) - { - //LOG << "Another EventLoop " << t_loopInThisThread << " exists in this thread " << threadId_; - } - else - { - t_loopInThisThread = this; - } - //pwakeupChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); - pwakeupChannel_->setEvents(EPOLLIN | EPOLLET); - pwakeupChannel_->setReadHandler(bind(&EventLoop::handleRead, this)); - pwakeupChannel_->setConnHandler(bind(&EventLoop::handleConn, this)); - poller_->epoll_add(pwakeupChannel_, 0); + : looping_(false), + poller_(new Epoll()), + wakeupFd_(createEventfd()), + quit_(false), + eventHandling_(false), + callingPendingFunctors_(false), + threadId_(CurrentThread::tid()), + pwakeupChannel_(new Channel(this, wakeupFd_)) { + if (t_loopInThisThread) { + // LOG << "Another EventLoop " << t_loopInThisThread << " exists in this + // thread " << threadId_; + } else { + t_loopInThisThread = this; + } + // pwakeupChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); + pwakeupChannel_->setEvents(EPOLLIN | EPOLLET); + pwakeupChannel_->setReadHandler(bind(&EventLoop::handleRead, this)); + pwakeupChannel_->setConnHandler(bind(&EventLoop::handleConn, this)); + poller_->epoll_add(pwakeupChannel_, 0); } -void EventLoop::handleConn() -{ - //poller_->epoll_mod(wakeupFd_, pwakeupChannel_, (EPOLLIN | EPOLLET | EPOLLONESHOT), 0); - updatePoller(pwakeupChannel_, 0); +void EventLoop::handleConn() { + // poller_->epoll_mod(wakeupFd_, pwakeupChannel_, (EPOLLIN | EPOLLET | + // EPOLLONESHOT), 0); + updatePoller(pwakeupChannel_, 0); } - -EventLoop::~EventLoop() -{ - //wakeupChannel_->disableAll(); - //wakeupChannel_->remove(); - close(wakeupFd_); - t_loopInThisThread = NULL; +EventLoop::~EventLoop() { + // wakeupChannel_->disableAll(); + // wakeupChannel_->remove(); + close(wakeupFd_); + t_loopInThisThread = NULL; } -void EventLoop::wakeup() -{ - uint64_t one = 1; - ssize_t n = writen(wakeupFd_, (char*)(&one), sizeof one); - if (n != sizeof one) - { - LOG<< "EventLoop::wakeup() writes " << n << " bytes instead of 8"; - } +void EventLoop::wakeup() { + uint64_t one = 1; + ssize_t n = writen(wakeupFd_, (char*)(&one), sizeof one); + if (n != sizeof one) { + LOG << "EventLoop::wakeup() writes " << n << " bytes instead of 8"; + } } -void EventLoop::handleRead() -{ - uint64_t one = 1; - ssize_t n = readn(wakeupFd_, &one, sizeof one); - if (n != sizeof one) - { - LOG << "EventLoop::handleRead() reads " << n << " bytes instead of 8"; - } - //pwakeupChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); - pwakeupChannel_->setEvents(EPOLLIN | EPOLLET); +void EventLoop::handleRead() { + uint64_t one = 1; + ssize_t n = readn(wakeupFd_, &one, sizeof one); + if (n != sizeof one) { + LOG << "EventLoop::handleRead() reads " << n << " bytes instead of 8"; + } + // pwakeupChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); + pwakeupChannel_->setEvents(EPOLLIN | EPOLLET); } -void EventLoop::runInLoop(Functor&& cb) -{ - if (isInLoopThread()) - cb(); - else - queueInLoop(std::move(cb)); +void EventLoop::runInLoop(Functor&& cb) { + if (isInLoopThread()) + cb(); + else + queueInLoop(std::move(cb)); } -void EventLoop::queueInLoop(Functor&& cb) -{ - { - MutexLockGuard lock(mutex_); - pendingFunctors_.emplace_back(std::move(cb)); - } +void EventLoop::queueInLoop(Functor&& cb) { + { + MutexLockGuard lock(mutex_); + pendingFunctors_.emplace_back(std::move(cb)); + } - if (!isInLoopThread() || callingPendingFunctors_) - wakeup(); + if (!isInLoopThread() || callingPendingFunctors_) wakeup(); } -void EventLoop::loop() -{ - assert(!looping_); - assert(isInLoopThread()); - looping_ = true; - quit_ = false; - //LOG_TRACE << "EventLoop " << this << " start looping"; - std::vector ret; - while (!quit_) - { - //cout << "doing" << endl; - ret.clear(); - ret = poller_->poll(); - eventHandling_ = true; - for (auto &it : ret) - it->handleEvents(); - eventHandling_ = false; - doPendingFunctors(); - poller_->handleExpired(); - } - looping_ = false; +void EventLoop::loop() { + assert(!looping_); + assert(isInLoopThread()); + looping_ = true; + quit_ = false; + // LOG_TRACE << "EventLoop " << this << " start looping"; + std::vector ret; + while (!quit_) { + // cout << "doing" << endl; + ret.clear(); + ret = poller_->poll(); + eventHandling_ = true; + for (auto& it : ret) it->handleEvents(); + eventHandling_ = false; + doPendingFunctors(); + poller_->handleExpired(); + } + looping_ = false; } -void EventLoop::doPendingFunctors() -{ - std::vector functors; - callingPendingFunctors_ = true; +void EventLoop::doPendingFunctors() { + std::vector functors; + callingPendingFunctors_ = true; - { - MutexLockGuard lock(mutex_); - functors.swap(pendingFunctors_); - } + { + MutexLockGuard lock(mutex_); + functors.swap(pendingFunctors_); + } - for (size_t i = 0; i < functors.size(); ++i) - functors[i](); - callingPendingFunctors_ = false; + for (size_t i = 0; i < functors.size(); ++i) functors[i](); + callingPendingFunctors_ = false; } -void EventLoop::quit() -{ - quit_ = true; - if (!isInLoopThread()) - { - wakeup(); - } +void EventLoop::quit() { + quit_ = true; + if (!isInLoopThread()) { + wakeup(); + } } \ No newline at end of file diff --git a/WebServer/EventLoop.h b/WebServer/EventLoop.h index 231df73..f712bb9 100755 --- a/WebServer/EventLoop.h +++ b/WebServer/EventLoop.h @@ -1,68 +1,58 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "base/Thread.h" -#include "Epoll.h" -#include "base/Logging.h" +#include +#include +#include #include "Channel.h" -#include "base/CurrentThread.h" +#include "Epoll.h" #include "Util.h" -#include -#include -#include +#include "base/CurrentThread.h" +#include "base/Logging.h" +#include "base/Thread.h" + #include using namespace std; +class EventLoop { + public: + typedef std::function Functor; + EventLoop(); + ~EventLoop(); + void loop(); + void quit(); + void runInLoop(Functor&& cb); + void queueInLoop(Functor&& cb); + bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); } + void assertInLoopThread() { assert(isInLoopThread()); } + void shutdown(shared_ptr channel) { shutDownWR(channel->getFd()); } + void removeFromPoller(shared_ptr channel) { + // shutDownWR(channel->getFd()); + poller_->epoll_del(channel); + } + void updatePoller(shared_ptr channel, int timeout = 0) { + poller_->epoll_mod(channel, timeout); + } + void addToPoller(shared_ptr channel, int timeout = 0) { + poller_->epoll_add(channel, timeout); + } + + private: + // 声明顺序 wakeupFd_ > pwakeupChannel_ + bool looping_; + shared_ptr poller_; + int wakeupFd_; + bool quit_; + bool eventHandling_; + mutable MutexLock mutex_; + std::vector pendingFunctors_; + bool callingPendingFunctors_; + const pid_t threadId_; + shared_ptr pwakeupChannel_; -class EventLoop -{ -public: - typedef std::function Functor; - EventLoop(); - ~EventLoop(); - void loop(); - void quit(); - void runInLoop(Functor&& cb); - void queueInLoop(Functor&& cb); - bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); } - void assertInLoopThread() - { - assert(isInLoopThread()); - } - void shutdown(shared_ptr channel) - { - shutDownWR(channel->getFd()); - } - void removeFromPoller(shared_ptr channel) - { - //shutDownWR(channel->getFd()); - poller_->epoll_del(channel); - } - void updatePoller(shared_ptr channel, int timeout = 0) - { - poller_->epoll_mod(channel, timeout); - } - void addToPoller(shared_ptr channel, int timeout = 0) - { - poller_->epoll_add(channel, timeout); - } - -private: - // 声明顺序 wakeupFd_ > pwakeupChannel_ - bool looping_; - shared_ptr poller_; - int wakeupFd_; - bool quit_; - bool eventHandling_; - mutable MutexLock mutex_; - std::vector pendingFunctors_; - bool callingPendingFunctors_; - const pid_t threadId_; - shared_ptr pwakeupChannel_; - - void wakeup(); - void handleRead(); - void doPendingFunctors(); - void handleConn(); + void wakeup(); + void handleRead(); + void doPendingFunctors(); + void handleConn(); }; diff --git a/WebServer/EventLoopThread.cpp b/WebServer/EventLoopThread.cpp index 37f056a..a2a23a6 100755 --- a/WebServer/EventLoopThread.cpp +++ b/WebServer/EventLoopThread.cpp @@ -3,49 +3,42 @@ #include "EventLoopThread.h" #include - EventLoopThread::EventLoopThread() -: loop_(NULL), - exiting_(false), - thread_(bind(&EventLoopThread::threadFunc, this), "EventLoopThread"), - mutex_(), - cond_(mutex_) -{ } + : loop_(NULL), + exiting_(false), + thread_(bind(&EventLoopThread::threadFunc, this), "EventLoopThread"), + mutex_(), + cond_(mutex_) {} -EventLoopThread::~EventLoopThread() -{ - exiting_ = true; - if (loop_ != NULL) - { - loop_->quit(); - thread_.join(); - } +EventLoopThread::~EventLoopThread() { + exiting_ = true; + if (loop_ != NULL) { + loop_->quit(); + thread_.join(); + } } -EventLoop* EventLoopThread::startLoop() -{ - assert(!thread_.started()); - thread_.start(); - { - MutexLockGuard lock(mutex_); - // 一直等到threadFun在Thread里真正跑起来 - while (loop_ == NULL) - cond_.wait(); - } - return loop_; +EventLoop* EventLoopThread::startLoop() { + assert(!thread_.started()); + thread_.start(); + { + MutexLockGuard lock(mutex_); + // 一直等到threadFun在Thread里真正跑起来 + while (loop_ == NULL) cond_.wait(); + } + return loop_; } -void EventLoopThread::threadFunc() -{ - EventLoop loop; +void EventLoopThread::threadFunc() { + EventLoop loop; - { - MutexLockGuard lock(mutex_); - loop_ = &loop; - cond_.notify(); - } + { + MutexLockGuard lock(mutex_); + loop_ = &loop; + cond_.notify(); + } - loop.loop(); - //assert(exiting_); - loop_ = NULL; + loop.loop(); + // assert(exiting_); + loop_ = NULL; } \ No newline at end of file diff --git a/WebServer/EventLoopThread.h b/WebServer/EventLoopThread.h index 16478ad..112937a 100755 --- a/WebServer/EventLoopThread.h +++ b/WebServer/EventLoopThread.h @@ -1,24 +1,24 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once +#include "EventLoop.h" #include "base/Condition.h" #include "base/MutexLock.h" #include "base/Thread.h" #include "base/noncopyable.h" -#include "EventLoop.h" -class EventLoopThread :noncopyable -{ -public: - EventLoopThread(); - ~EventLoopThread(); - EventLoop* startLoop(); -private: - void threadFunc(); - EventLoop *loop_; - bool exiting_; - Thread thread_; - MutexLock mutex_; - Condition cond_; +class EventLoopThread : noncopyable { + public: + EventLoopThread(); + ~EventLoopThread(); + EventLoop* startLoop(); + + private: + void threadFunc(); + EventLoop* loop_; + bool exiting_; + Thread thread_; + MutexLock mutex_; + Condition cond_; }; \ No newline at end of file diff --git a/WebServer/EventLoopThreadPool.cpp b/WebServer/EventLoopThreadPool.cpp index d77f802..a735225 100755 --- a/WebServer/EventLoopThreadPool.cpp +++ b/WebServer/EventLoopThreadPool.cpp @@ -2,40 +2,31 @@ // @Email xxbbb@vip.qq.com #include "EventLoopThreadPool.h" -EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, int numThreads) -: baseLoop_(baseLoop), - started_(false), - numThreads_(numThreads), - next_(0) -{ - if (numThreads_ <= 0) - { - LOG << "numThreads_ <= 0"; - abort(); - } +EventLoopThreadPool::EventLoopThreadPool(EventLoop *baseLoop, int numThreads) + : baseLoop_(baseLoop), started_(false), numThreads_(numThreads), next_(0) { + if (numThreads_ <= 0) { + LOG << "numThreads_ <= 0"; + abort(); + } } -void EventLoopThreadPool::start() -{ - baseLoop_->assertInLoopThread(); - started_ = true; - for (int i = 0; i < numThreads_; ++i) - { - std::shared_ptr t(new EventLoopThread()); - threads_.push_back(t); - loops_.push_back(t->startLoop()); - } +void EventLoopThreadPool::start() { + baseLoop_->assertInLoopThread(); + started_ = true; + for (int i = 0; i < numThreads_; ++i) { + std::shared_ptr t(new EventLoopThread()); + threads_.push_back(t); + loops_.push_back(t->startLoop()); + } } -EventLoop *EventLoopThreadPool::getNextLoop() -{ - baseLoop_->assertInLoopThread(); - assert(started_); - EventLoop *loop = baseLoop_; - if (!loops_.empty()) - { - loop = loops_[next_]; - next_ = (next_ + 1) % numThreads_; - } - return loop; +EventLoop *EventLoopThreadPool::getNextLoop() { + baseLoop_->assertInLoopThread(); + assert(started_); + EventLoop *loop = baseLoop_; + if (!loops_.empty()) { + loop = loops_[next_]; + next_ = (next_ + 1) % numThreads_; + } + return loop; } \ No newline at end of file diff --git a/WebServer/EventLoopThreadPool.h b/WebServer/EventLoopThreadPool.h index b2a6104..7475bd6 100755 --- a/WebServer/EventLoopThreadPool.h +++ b/WebServer/EventLoopThreadPool.h @@ -1,30 +1,27 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "base/noncopyable.h" -#include "EventLoopThread.h" -#include "base/Logging.h" #include #include +#include "EventLoopThread.h" +#include "base/Logging.h" +#include "base/noncopyable.h" + -class EventLoopThreadPool : noncopyable -{ -public: - EventLoopThreadPool(EventLoop* baseLoop, int numThreads); +class EventLoopThreadPool : noncopyable { + public: + EventLoopThreadPool(EventLoop* baseLoop, int numThreads); - ~EventLoopThreadPool() - { - LOG << "~EventLoopThreadPool()"; - } - void start(); + ~EventLoopThreadPool() { LOG << "~EventLoopThreadPool()"; } + void start(); - EventLoop *getNextLoop(); + EventLoop* getNextLoop(); -private: - EventLoop* baseLoop_; - bool started_; - int numThreads_; - int next_; - std::vector> threads_; - std::vector loops_; + private: + EventLoop* baseLoop_; + bool started_; + int numThreads_; + int next_; + std::vector> threads_; + std::vector loops_; }; \ No newline at end of file diff --git a/WebServer/HttpData.cpp b/WebServer/HttpData.cpp index 821777a..2bbe7ce 100755 --- a/WebServer/HttpData.cpp +++ b/WebServer/HttpData.cpp @@ -1,729 +1,616 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "HttpData.h" -#include "time.h" -#include "Channel.h" -#include "Util.h" -#include "EventLoop.h" #include -#include #include +#include #include +#include "Channel.h" +#include "EventLoop.h" +#include "Util.h" +#include "time.h" + using namespace std; pthread_once_t MimeType::once_control = PTHREAD_ONCE_INIT; std::unordered_map MimeType::mime; - const __uint32_t DEFAULT_EVENT = EPOLLIN | EPOLLET | EPOLLONESHOT; -const int DEFAULT_EXPIRED_TIME = 2000; // ms -const int DEFAULT_KEEP_ALIVE_TIME = 5 * 60 * 1000; // ms +const int DEFAULT_EXPIRED_TIME = 2000; // ms +const int DEFAULT_KEEP_ALIVE_TIME = 5 * 60 * 1000; // ms char favicon[555] = { - '\x89', 'P', 'N', 'G', '\xD', '\xA', '\x1A', '\xA', - '\x0', '\x0', '\x0', '\xD', 'I', 'H', 'D', 'R', - '\x0', '\x0', '\x0', '\x10', '\x0', '\x0', '\x0', '\x10', - '\x8', '\x6', '\x0', '\x0', '\x0', '\x1F', '\xF3', '\xFF', - 'a', '\x0', '\x0', '\x0', '\x19', 't', 'E', 'X', - 't', 'S', 'o', 'f', 't', 'w', 'a', 'r', - 'e', '\x0', 'A', 'd', 'o', 'b', 'e', '\x20', - 'I', 'm', 'a', 'g', 'e', 'R', 'e', 'a', - 'd', 'y', 'q', '\xC9', 'e', '\x3C', '\x0', '\x0', - '\x1', '\xCD', 'I', 'D', 'A', 'T', 'x', '\xDA', - '\x94', '\x93', '9', 'H', '\x3', 'A', '\x14', '\x86', - '\xFF', '\x5D', 'b', '\xA7', '\x4', 'R', '\xC4', 'm', - '\x22', '\x1E', '\xA0', 'F', '\x24', '\x8', '\x16', '\x16', - 'v', '\xA', '6', '\xBA', 'J', '\x9A', '\x80', '\x8', - 'A', '\xB4', 'q', '\x85', 'X', '\x89', 'G', '\xB0', - 'I', '\xA9', 'Q', '\x24', '\xCD', '\xA6', '\x8', '\xA4', - 'H', 'c', '\x91', 'B', '\xB', '\xAF', 'V', '\xC1', - 'F', '\xB4', '\x15', '\xCF', '\x22', 'X', '\x98', '\xB', - 'T', 'H', '\x8A', 'd', '\x93', '\x8D', '\xFB', 'F', - 'g', '\xC9', '\x1A', '\x14', '\x7D', '\xF0', 'f', 'v', - 'f', '\xDF', '\x7C', '\xEF', '\xE7', 'g', 'F', '\xA8', - '\xD5', 'j', 'H', '\x24', '\x12', '\x2A', '\x0', '\x5', - '\xBF', 'G', '\xD4', '\xEF', '\xF7', '\x2F', '6', '\xEC', - '\x12', '\x20', '\x1E', '\x8F', '\xD7', '\xAA', '\xD5', '\xEA', - '\xAF', 'I', '5', 'F', '\xAA', 'T', '\x5F', '\x9F', - '\x22', 'A', '\x2A', '\x95', '\xA', '\x83', '\xE5', 'r', - '9', 'd', '\xB3', 'Y', '\x96', '\x99', 'L', '\x6', - '\xE9', 't', '\x9A', '\x25', '\x85', '\x2C', '\xCB', 'T', - '\xA7', '\xC4', 'b', '1', '\xB5', '\x5E', '\x0', '\x3', - 'h', '\x9A', '\xC6', '\x16', '\x82', '\x20', 'X', 'R', - '\x14', 'E', '6', 'S', '\x94', '\xCB', 'e', 'x', - '\xBD', '\x5E', '\xAA', 'U', 'T', '\x23', 'L', '\xC0', - '\xE0', '\xE2', '\xC1', '\x8F', '\x0', '\x9E', '\xBC', '\x9', - 'A', '\x7C', '\x3E', '\x1F', '\x83', 'D', '\x22', '\x11', - '\xD5', 'T', '\x40', '\x3F', '8', '\x80', 'w', '\xE5', - '3', '\x7', '\xB8', '\x5C', '\x2E', 'H', '\x92', '\x4', - '\x87', '\xC3', '\x81', '\x40', '\x20', '\x40', 'g', '\x98', - '\xE9', '6', '\x1A', '\xA6', 'g', '\x15', '\x4', '\xE3', - '\xD7', '\xC8', '\xBD', '\x15', '\xE1', 'i', '\xB7', 'C', - '\xAB', '\xEA', 'x', '\x2F', 'j', 'X', '\x92', '\xBB', - '\x18', '\x20', '\x9F', '\xCF', '3', '\xC3', '\xB8', '\xE9', - 'N', '\xA7', '\xD3', 'l', 'J', '\x0', 'i', '6', - '\x7C', '\x8E', '\xE1', '\xFE', 'V', '\x84', '\xE7', '\x3C', - '\x9F', 'r', '\x2B', '\x3A', 'B', '\x7B', '7', 'f', - 'w', '\xAE', '\x8E', '\xE', '\xF3', '\xBD', 'R', '\xA9', - 'd', '\x2', 'B', '\xAF', '\x85', '2', 'f', 'F', - '\xBA', '\xC', '\xD9', '\x9F', '\x1D', '\x9A', 'l', '\x22', - '\xE6', '\xC7', '\x3A', '\x2C', '\x80', '\xEF', '\xC1', '\x15', - '\x90', '\x7', '\x93', '\xA2', '\x28', '\xA0', 'S', 'j', - '\xB1', '\xB8', '\xDF', '\x29', '5', 'C', '\xE', '\x3F', - 'X', '\xFC', '\x98', '\xDA', 'y', 'j', 'P', '\x40', - '\x0', '\x87', '\xAE', '\x1B', '\x17', 'B', '\xB4', '\x3A', - '\x3F', '\xBE', 'y', '\xC7', '\xA', '\x26', '\xB6', '\xEE', - '\xD9', '\x9A', '\x60', '\x14', '\x93', '\xDB', '\x8F', '\xD', - '\xA', '\x2E', '\xE9', '\x23', '\x95', '\x29', 'X', '\x0', - '\x27', '\xEB', 'n', 'V', 'p', '\xBC', '\xD6', '\xCB', - '\xD6', 'G', '\xAB', '\x3D', 'l', '\x7D', '\xB8', '\xD2', - '\xDD', '\xA0', '\x60', '\x83', '\xBA', '\xEF', '\x5F', '\xA4', - '\xEA', '\xCC', '\x2', 'N', '\xAE', '\x5E', 'p', '\x1A', - '\xEC', '\xB3', '\x40', '9', '\xAC', '\xFE', '\xF2', '\x91', - '\x89', 'g', '\x91', '\x85', '\x21', '\xA8', '\x87', '\xB7', - 'X', '\x7E', '\x7E', '\x85', '\xBB', '\xCD', 'N', 'N', - 'b', 't', '\x40', '\xFA', '\x93', '\x89', '\xEC', '\x1E', - '\xEC', '\x86', '\x2', 'H', '\x26', '\x93', '\xD0', 'u', - '\x1D', '\x7F', '\x9', '2', '\x95', '\xBF', '\x1F', '\xDB', - '\xD7', 'c', '\x8A', '\x1A', '\xF7', '\x5C', '\xC1', '\xFF', - '\x22', 'J', '\xC3', '\x87', '\x0', '\x3', '\x0', 'K', - '\xBB', '\xF8', '\xD6', '\x2A', 'v', '\x98', 'I', '\x0', - '\x0', '\x0', '\x0', 'I', 'E', 'N', 'D', '\xAE', - 'B', '\x60', '\x82', + '\x89', 'P', 'N', 'G', '\xD', '\xA', '\x1A', '\xA', '\x0', + '\x0', '\x0', '\xD', 'I', 'H', 'D', 'R', '\x0', '\x0', + '\x0', '\x10', '\x0', '\x0', '\x0', '\x10', '\x8', '\x6', '\x0', + '\x0', '\x0', '\x1F', '\xF3', '\xFF', 'a', '\x0', '\x0', '\x0', + '\x19', 't', 'E', 'X', 't', 'S', 'o', 'f', 't', + 'w', 'a', 'r', 'e', '\x0', 'A', 'd', 'o', 'b', + 'e', '\x20', 'I', 'm', 'a', 'g', 'e', 'R', 'e', + 'a', 'd', 'y', 'q', '\xC9', 'e', '\x3C', '\x0', '\x0', + '\x1', '\xCD', 'I', 'D', 'A', 'T', 'x', '\xDA', '\x94', + '\x93', '9', 'H', '\x3', 'A', '\x14', '\x86', '\xFF', '\x5D', + 'b', '\xA7', '\x4', 'R', '\xC4', 'm', '\x22', '\x1E', '\xA0', + 'F', '\x24', '\x8', '\x16', '\x16', 'v', '\xA', '6', '\xBA', + 'J', '\x9A', '\x80', '\x8', 'A', '\xB4', 'q', '\x85', 'X', + '\x89', 'G', '\xB0', 'I', '\xA9', 'Q', '\x24', '\xCD', '\xA6', + '\x8', '\xA4', 'H', 'c', '\x91', 'B', '\xB', '\xAF', 'V', + '\xC1', 'F', '\xB4', '\x15', '\xCF', '\x22', 'X', '\x98', '\xB', + 'T', 'H', '\x8A', 'd', '\x93', '\x8D', '\xFB', 'F', 'g', + '\xC9', '\x1A', '\x14', '\x7D', '\xF0', 'f', 'v', 'f', '\xDF', + '\x7C', '\xEF', '\xE7', 'g', 'F', '\xA8', '\xD5', 'j', 'H', + '\x24', '\x12', '\x2A', '\x0', '\x5', '\xBF', 'G', '\xD4', '\xEF', + '\xF7', '\x2F', '6', '\xEC', '\x12', '\x20', '\x1E', '\x8F', '\xD7', + '\xAA', '\xD5', '\xEA', '\xAF', 'I', '5', 'F', '\xAA', 'T', + '\x5F', '\x9F', '\x22', 'A', '\x2A', '\x95', '\xA', '\x83', '\xE5', + 'r', '9', 'd', '\xB3', 'Y', '\x96', '\x99', 'L', '\x6', + '\xE9', 't', '\x9A', '\x25', '\x85', '\x2C', '\xCB', 'T', '\xA7', + '\xC4', 'b', '1', '\xB5', '\x5E', '\x0', '\x3', 'h', '\x9A', + '\xC6', '\x16', '\x82', '\x20', 'X', 'R', '\x14', 'E', '6', + 'S', '\x94', '\xCB', 'e', 'x', '\xBD', '\x5E', '\xAA', 'U', + 'T', '\x23', 'L', '\xC0', '\xE0', '\xE2', '\xC1', '\x8F', '\x0', + '\x9E', '\xBC', '\x9', 'A', '\x7C', '\x3E', '\x1F', '\x83', 'D', + '\x22', '\x11', '\xD5', 'T', '\x40', '\x3F', '8', '\x80', 'w', + '\xE5', '3', '\x7', '\xB8', '\x5C', '\x2E', 'H', '\x92', '\x4', + '\x87', '\xC3', '\x81', '\x40', '\x20', '\x40', 'g', '\x98', '\xE9', + '6', '\x1A', '\xA6', 'g', '\x15', '\x4', '\xE3', '\xD7', '\xC8', + '\xBD', '\x15', '\xE1', 'i', '\xB7', 'C', '\xAB', '\xEA', 'x', + '\x2F', 'j', 'X', '\x92', '\xBB', '\x18', '\x20', '\x9F', '\xCF', + '3', '\xC3', '\xB8', '\xE9', 'N', '\xA7', '\xD3', 'l', 'J', + '\x0', 'i', '6', '\x7C', '\x8E', '\xE1', '\xFE', 'V', '\x84', + '\xE7', '\x3C', '\x9F', 'r', '\x2B', '\x3A', 'B', '\x7B', '7', + 'f', 'w', '\xAE', '\x8E', '\xE', '\xF3', '\xBD', 'R', '\xA9', + 'd', '\x2', 'B', '\xAF', '\x85', '2', 'f', 'F', '\xBA', + '\xC', '\xD9', '\x9F', '\x1D', '\x9A', 'l', '\x22', '\xE6', '\xC7', + '\x3A', '\x2C', '\x80', '\xEF', '\xC1', '\x15', '\x90', '\x7', '\x93', + '\xA2', '\x28', '\xA0', 'S', 'j', '\xB1', '\xB8', '\xDF', '\x29', + '5', 'C', '\xE', '\x3F', 'X', '\xFC', '\x98', '\xDA', 'y', + 'j', 'P', '\x40', '\x0', '\x87', '\xAE', '\x1B', '\x17', 'B', + '\xB4', '\x3A', '\x3F', '\xBE', 'y', '\xC7', '\xA', '\x26', '\xB6', + '\xEE', '\xD9', '\x9A', '\x60', '\x14', '\x93', '\xDB', '\x8F', '\xD', + '\xA', '\x2E', '\xE9', '\x23', '\x95', '\x29', 'X', '\x0', '\x27', + '\xEB', 'n', 'V', 'p', '\xBC', '\xD6', '\xCB', '\xD6', 'G', + '\xAB', '\x3D', 'l', '\x7D', '\xB8', '\xD2', '\xDD', '\xA0', '\x60', + '\x83', '\xBA', '\xEF', '\x5F', '\xA4', '\xEA', '\xCC', '\x2', 'N', + '\xAE', '\x5E', 'p', '\x1A', '\xEC', '\xB3', '\x40', '9', '\xAC', + '\xFE', '\xF2', '\x91', '\x89', 'g', '\x91', '\x85', '\x21', '\xA8', + '\x87', '\xB7', 'X', '\x7E', '\x7E', '\x85', '\xBB', '\xCD', 'N', + 'N', 'b', 't', '\x40', '\xFA', '\x93', '\x89', '\xEC', '\x1E', + '\xEC', '\x86', '\x2', 'H', '\x26', '\x93', '\xD0', 'u', '\x1D', + '\x7F', '\x9', '2', '\x95', '\xBF', '\x1F', '\xDB', '\xD7', 'c', + '\x8A', '\x1A', '\xF7', '\x5C', '\xC1', '\xFF', '\x22', 'J', '\xC3', + '\x87', '\x0', '\x3', '\x0', 'K', '\xBB', '\xF8', '\xD6', '\x2A', + 'v', '\x98', 'I', '\x0', '\x0', '\x0', '\x0', 'I', 'E', + 'N', 'D', '\xAE', 'B', '\x60', '\x82', }; -void MimeType::init() -{ - 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"] = "image/x-icon"; - mime[".jpg"] = "image/jpeg"; - mime[".png"] = "image/png"; - mime[".txt"] = "text/plain"; - mime[".mp3"] = "audio/mp3"; - mime["default"] = "text/html"; +void MimeType::init() { + 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"] = "image/x-icon"; + mime[".jpg"] = "image/jpeg"; + mime[".png"] = "image/png"; + mime[".txt"] = "text/plain"; + mime[".mp3"] = "audio/mp3"; + mime["default"] = "text/html"; } -std::string MimeType::getMime(const std::string &suffix) -{ - pthread_once(&once_control, MimeType::init); - if (mime.find(suffix) == mime.end()) - return mime["default"]; - else - return mime[suffix]; +std::string MimeType::getMime(const std::string &suffix) { + pthread_once(&once_control, MimeType::init); + if (mime.find(suffix) == mime.end()) + return mime["default"]; + else + return mime[suffix]; } - -HttpData::HttpData(EventLoop *loop, int connfd): - loop_(loop), - channel_(new Channel(loop, connfd)), - fd_(connfd), - error_(false), - connectionState_(H_CONNECTED), - method_(METHOD_GET), - HTTPVersion_(HTTP_11), - nowReadPos_(0), - state_(STATE_PARSE_URI), - hState_(H_START), - keepAlive_(false) -{ - //loop_->queueInLoop(bind(&HttpData::setHandlers, this)); - channel_->setReadHandler(bind(&HttpData::handleRead, this)); - channel_->setWriteHandler(bind(&HttpData::handleWrite, this)); - channel_->setConnHandler(bind(&HttpData::handleConn, this)); +HttpData::HttpData(EventLoop *loop, int connfd) + : loop_(loop), + channel_(new Channel(loop, connfd)), + fd_(connfd), + error_(false), + connectionState_(H_CONNECTED), + method_(METHOD_GET), + HTTPVersion_(HTTP_11), + nowReadPos_(0), + state_(STATE_PARSE_URI), + hState_(H_START), + keepAlive_(false) { + // loop_->queueInLoop(bind(&HttpData::setHandlers, this)); + channel_->setReadHandler(bind(&HttpData::handleRead, this)); + channel_->setWriteHandler(bind(&HttpData::handleWrite, this)); + channel_->setConnHandler(bind(&HttpData::handleConn, this)); } -void HttpData::reset() -{ - //inBuffer_.clear(); - fileName_.clear(); - path_.clear(); - nowReadPos_ = 0; - state_ = STATE_PARSE_URI; - hState_ = H_START; - headers_.clear(); - //keepAlive_ = false; - if (timer_.lock()) - { - shared_ptr my_timer(timer_.lock()); - my_timer->clearReq(); - timer_.reset(); - } +void HttpData::reset() { + // inBuffer_.clear(); + fileName_.clear(); + path_.clear(); + nowReadPos_ = 0; + state_ = STATE_PARSE_URI; + hState_ = H_START; + headers_.clear(); + // keepAlive_ = false; + if (timer_.lock()) { + shared_ptr my_timer(timer_.lock()); + my_timer->clearReq(); + timer_.reset(); + } } -void HttpData::seperateTimer() -{ - //cout << "seperateTimer" << endl; - if (timer_.lock()) - { - shared_ptr my_timer(timer_.lock()); - my_timer->clearReq(); - timer_.reset(); - } +void HttpData::seperateTimer() { + // cout << "seperateTimer" << endl; + if (timer_.lock()) { + shared_ptr my_timer(timer_.lock()); + my_timer->clearReq(); + timer_.reset(); + } } -void HttpData::handleRead() -{ - __uint32_t &events_ = channel_->getEvents(); - do - { - bool zero = false; - int read_num = readn(fd_, inBuffer_, zero); - LOG << "Request: " << inBuffer_; - if (connectionState_ == H_DISCONNECTING) - { - inBuffer_.clear(); - break; - } - //cout << inBuffer_ << endl; - if (read_num < 0) - { - perror("1"); - error_ = true; - handleError(fd_, 400, "Bad Request"); - break; - } - // else if (read_num == 0) - // { - // error_ = true; - // break; - // } - else if (zero) - { - // 有请求出现但是读不到数据,可能是Request Aborted,或者来自网络的数据没有达到等原因 - // 最可能是对端已经关闭了,统一按照对端已经关闭处理 - //error_ = true; - connectionState_ = H_DISCONNECTING; - if (read_num == 0) - { - //error_ = true; - break; - } - //cout << "readnum == 0" << endl; - } - - - if (state_ == STATE_PARSE_URI) - { - URIState flag = this->parseURI(); - if (flag == PARSE_URI_AGAIN) - break; - else if (flag == PARSE_URI_ERROR) - { - perror("2"); - LOG << "FD = " << fd_ << "," << inBuffer_ << "******"; - inBuffer_.clear(); - error_ = true; - handleError(fd_, 400, "Bad Request"); - break; - } - else - state_ = STATE_PARSE_HEADERS; - } - if (state_ == STATE_PARSE_HEADERS) - { - HeaderState flag = this->parseHeaders(); - if (flag == PARSE_HEADER_AGAIN) - break; - else if (flag == PARSE_HEADER_ERROR) - { - perror("3"); - error_ = true; - handleError(fd_, 400, "Bad Request"); - break; - } - if(method_ == METHOD_POST) - { - // 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 - { - //cout << "(state_ == STATE_RECV_BODY)" << endl; - error_ = true; - handleError(fd_, 400, "Bad Request: Lack of argument (Content-length)"); - break; - } - if (static_cast(inBuffer_.size()) < content_length) - break; - state_ = STATE_ANALYSIS; - } - if (state_ == STATE_ANALYSIS) - { - AnalysisState flag = this->analysisRequest(); - if (flag == ANALYSIS_SUCCESS) - { - state_ = STATE_FINISH; - break; - } - else - { - //cout << "state_ == STATE_ANALYSIS" << endl; - error_ = true; - break; - } - } - } while (false); - //cout << "state_=" << state_ << endl; - if (!error_) - { - if (outBuffer_.size() > 0) - { - handleWrite(); - //events_ |= EPOLLOUT; - } - // error_ may change - if (!error_ && state_ == STATE_FINISH) - { - this->reset(); - if (inBuffer_.size() > 0) - { - if (connectionState_ != H_DISCONNECTING) - handleRead(); - } - - // if ((keepAlive_ || inBuffer_.size() > 0) && connectionState_ == H_CONNECTED) - // { - // this->reset(); - // events_ |= EPOLLIN; - // } - } - else if (!error_ && connectionState_ != H_DISCONNECTED) - events_ |= EPOLLIN; +void HttpData::handleRead() { + __uint32_t &events_ = channel_->getEvents(); + do { + bool zero = false; + int read_num = readn(fd_, inBuffer_, zero); + LOG << "Request: " << inBuffer_; + if (connectionState_ == H_DISCONNECTING) { + inBuffer_.clear(); + break; } -} - -void HttpData::handleWrite() -{ - if (!error_ && connectionState_ != H_DISCONNECTED) - { - __uint32_t &events_ = channel_->getEvents(); - if (writen(fd_, outBuffer_) < 0) - { - perror("writen"); - events_ = 0; - error_ = true; - } - if (outBuffer_.size() > 0) - events_ |= EPOLLOUT; + // cout << inBuffer_ << endl; + if (read_num < 0) { + perror("1"); + error_ = true; + handleError(fd_, 400, "Bad Request"); + break; + } + // else if (read_num == 0) + // { + // error_ = true; + // break; + // } + else if (zero) { + // 有请求出现但是读不到数据,可能是Request + // Aborted,或者来自网络的数据没有达到等原因 + // 最可能是对端已经关闭了,统一按照对端已经关闭处理 + // error_ = true; + connectionState_ = H_DISCONNECTING; + if (read_num == 0) { + // error_ = true; + break; + } + // cout << "readnum == 0" << endl; } -} - -void HttpData::handleConn() -{ - seperateTimer(); - __uint32_t &events_ = channel_->getEvents(); - if (!error_ && connectionState_ == H_CONNECTED) - { - if (events_ != 0) - { - int timeout = DEFAULT_EXPIRED_TIME; - if (keepAlive_) - timeout = DEFAULT_KEEP_ALIVE_TIME; - if ((events_ & EPOLLIN) && (events_ & EPOLLOUT)) - { - events_ = __uint32_t(0); - events_ |= EPOLLOUT; - } - //events_ |= (EPOLLET | EPOLLONESHOT); - events_ |= EPOLLET; - loop_->updatePoller(channel_, timeout); - } - else if (keepAlive_) - { - events_ |= (EPOLLIN | EPOLLET); - //events_ |= (EPOLLIN | EPOLLET | EPOLLONESHOT); - int timeout = DEFAULT_KEEP_ALIVE_TIME; - loop_->updatePoller(channel_, timeout); - } - else - { - //cout << "close normally" << endl; - // loop_->shutdown(channel_); - // loop_->runInLoop(bind(&HttpData::handleClose, shared_from_this())); - events_ |= (EPOLLIN | EPOLLET); - //events_ |= (EPOLLIN | EPOLLET | EPOLLONESHOT); - int timeout = (DEFAULT_KEEP_ALIVE_TIME >> 1); - loop_->updatePoller(channel_, timeout); - } + if (state_ == STATE_PARSE_URI) { + URIState flag = this->parseURI(); + if (flag == PARSE_URI_AGAIN) + break; + else if (flag == PARSE_URI_ERROR) { + perror("2"); + LOG << "FD = " << fd_ << "," << inBuffer_ << "******"; + inBuffer_.clear(); + error_ = true; + handleError(fd_, 400, "Bad Request"); + break; + } else + state_ = STATE_PARSE_HEADERS; } - else if (!error_ && connectionState_ == H_DISCONNECTING && (events_ & EPOLLOUT)) - { - events_ = (EPOLLOUT | EPOLLET); + if (state_ == STATE_PARSE_HEADERS) { + HeaderState flag = this->parseHeaders(); + if (flag == PARSE_HEADER_AGAIN) + break; + else if (flag == PARSE_HEADER_ERROR) { + perror("3"); + error_ = true; + handleError(fd_, 400, "Bad Request"); + break; + } + if (method_ == METHOD_POST) { + // POST方法准备 + state_ = STATE_RECV_BODY; + } else { + state_ = STATE_ANALYSIS; + } } - else - { - //cout << "close with errors" << endl; - loop_->runInLoop(bind(&HttpData::handleClose, shared_from_this())); + if (state_ == STATE_RECV_BODY) { + int content_length = -1; + if (headers_.find("Content-length") != headers_.end()) { + content_length = stoi(headers_["Content-length"]); + } else { + // cout << "(state_ == STATE_RECV_BODY)" << endl; + error_ = true; + handleError(fd_, 400, "Bad Request: Lack of argument (Content-length)"); + break; + } + if (static_cast(inBuffer_.size()) < content_length) break; + state_ = STATE_ANALYSIS; + } + if (state_ == STATE_ANALYSIS) { + AnalysisState flag = this->analysisRequest(); + if (flag == ANALYSIS_SUCCESS) { + state_ = STATE_FINISH; + break; + } else { + // cout << "state_ == STATE_ANALYSIS" << endl; + error_ = true; + break; + } + } + } while (false); + // cout << "state_=" << state_ << endl; + if (!error_) { + if (outBuffer_.size() > 0) { + handleWrite(); + // events_ |= EPOLLOUT; } + // error_ may change + if (!error_ && state_ == STATE_FINISH) { + this->reset(); + if (inBuffer_.size() > 0) { + if (connectionState_ != H_DISCONNECTING) handleRead(); + } + + // if ((keepAlive_ || inBuffer_.size() > 0) && connectionState_ == + // H_CONNECTED) + // { + // this->reset(); + // events_ |= EPOLLIN; + // } + } else if (!error_ && connectionState_ != H_DISCONNECTED) + events_ |= EPOLLIN; + } } - -URIState HttpData::parseURI() -{ - string &str = inBuffer_; - string cop = str; - // 读到完整的请求行再开始解析请求 - size_t pos = str.find('\r', nowReadPos_); - if (pos < 0) - { - return PARSE_URI_AGAIN; +void HttpData::handleWrite() { + if (!error_ && connectionState_ != H_DISCONNECTED) { + __uint32_t &events_ = channel_->getEvents(); + if (writen(fd_, outBuffer_) < 0) { + perror("writen"); + events_ = 0; + error_ = true; } - // 去掉请求行所占的空间,节省空间 - string request_line = str.substr(0, pos); - if (str.size() > pos + 1) - str = str.substr(pos + 1); - else - str.clear(); - // Method - int posGet = request_line.find("GET"); - int posPost = request_line.find("POST"); - int posHead = request_line.find("HEAD"); + if (outBuffer_.size() > 0) events_ |= EPOLLOUT; + } +} - if (posGet >= 0) - { - pos = posGet; - method_ = METHOD_GET; - } - else if (posPost >= 0) - { - pos = posPost; - method_ = METHOD_POST; - } - else if (posHead >= 0) - { - pos = posHead; - method_ = METHOD_HEAD; - } - else - { - return PARSE_URI_ERROR; +void HttpData::handleConn() { + seperateTimer(); + __uint32_t &events_ = channel_->getEvents(); + if (!error_ && connectionState_ == H_CONNECTED) { + if (events_ != 0) { + int timeout = DEFAULT_EXPIRED_TIME; + if (keepAlive_) timeout = DEFAULT_KEEP_ALIVE_TIME; + if ((events_ & EPOLLIN) && (events_ & EPOLLOUT)) { + events_ = __uint32_t(0); + events_ |= EPOLLOUT; + } + // events_ |= (EPOLLET | EPOLLONESHOT); + events_ |= EPOLLET; + loop_->updatePoller(channel_, timeout); + + } else if (keepAlive_) { + events_ |= (EPOLLIN | EPOLLET); + // events_ |= (EPOLLIN | EPOLLET | EPOLLONESHOT); + int timeout = DEFAULT_KEEP_ALIVE_TIME; + loop_->updatePoller(channel_, timeout); + } else { + // cout << "close normally" << endl; + // loop_->shutdown(channel_); + // loop_->runInLoop(bind(&HttpData::handleClose, shared_from_this())); + events_ |= (EPOLLIN | EPOLLET); + // events_ |= (EPOLLIN | EPOLLET | EPOLLONESHOT); + int timeout = (DEFAULT_KEEP_ALIVE_TIME >> 1); + loop_->updatePoller(channel_, timeout); } + } else if (!error_ && connectionState_ == H_DISCONNECTING && + (events_ & EPOLLOUT)) { + events_ = (EPOLLOUT | EPOLLET); + } else { + // cout << "close with errors" << endl; + loop_->runInLoop(bind(&HttpData::handleClose, shared_from_this())); + } +} - // filename - pos = request_line.find("/", pos); - if (pos < 0) - { - fileName_ = "index.html"; - HTTPVersion_ = HTTP_11; - return PARSE_URI_SUCCESS; - } - else - { - size_t _pos = request_line.find(' ', pos); - if (_pos < 0) - return PARSE_URI_ERROR; - else - { - if (_pos - pos > 1) - { - fileName_ = request_line.substr(pos + 1, _pos - pos - 1); - size_t __pos = fileName_.find('?'); - if (__pos >= 0) - { - fileName_ = fileName_.substr(0, __pos); - } - } - - else - fileName_ = "index.html"; +URIState HttpData::parseURI() { + string &str = inBuffer_; + string cop = str; + // 读到完整的请求行再开始解析请求 + size_t pos = str.find('\r', nowReadPos_); + 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 + int posGet = request_line.find("GET"); + int posPost = request_line.find("POST"); + int posHead = request_line.find("HEAD"); + + if (posGet >= 0) { + pos = posGet; + method_ = METHOD_GET; + } else if (posPost >= 0) { + pos = posPost; + method_ = METHOD_POST; + } else if (posHead >= 0) { + pos = posHead; + method_ = METHOD_HEAD; + } else { + return PARSE_URI_ERROR; + } + + // filename + pos = request_line.find("/", pos); + if (pos < 0) { + fileName_ = "index.html"; + HTTPVersion_ = HTTP_11; + return PARSE_URI_SUCCESS; + } else { + size_t _pos = request_line.find(' ', pos); + if (_pos < 0) + return PARSE_URI_ERROR; + else { + if (_pos - pos > 1) { + fileName_ = request_line.substr(pos + 1, _pos - pos - 1); + size_t __pos = fileName_.find('?'); + if (__pos >= 0) { + fileName_ = fileName_.substr(0, __pos); } - pos = _pos; + } + + else + fileName_ = "index.html"; } - //cout << "fileName_: " << fileName_ << endl; - // HTTP 版本号 - pos = request_line.find("/", pos); - if (pos < 0) + pos = _pos; + } + // cout << "fileName_: " << fileName_ << endl; + // HTTP 版本号 + pos = request_line.find("/", pos); + if (pos < 0) + return PARSE_URI_ERROR; + else { + if (request_line.size() - pos <= 3) + return PARSE_URI_ERROR; + else { + string ver = request_line.substr(pos + 1, 3); + if (ver == "1.0") + HTTPVersion_ = HTTP_10; + else if (ver == "1.1") + HTTPVersion_ = HTTP_11; + else return PARSE_URI_ERROR; - else - { - if (request_line.size() - pos <= 3) - return PARSE_URI_ERROR; - else - { - string ver = request_line.substr(pos + 1, 3); - if (ver == "1.0") - HTTPVersion_ = HTTP_10; - else if (ver == "1.1") - HTTPVersion_ = HTTP_11; - else - return PARSE_URI_ERROR; - } } - return PARSE_URI_SUCCESS; + } + return PARSE_URI_SUCCESS; } -HeaderState HttpData::parseHeaders() -{ - string &str = inBuffer_; - int key_start = -1, key_end = -1, value_start = -1, value_end = -1; - int now_read_line_begin = 0; - bool notFinish = true; - size_t i = 0; - for (; i < str.size() && notFinish; ++i) - { - switch(hState_) - { - case H_START: - { - if (str[i] == '\n' || str[i] == '\r') - break; - hState_ = H_KEY; - key_start = i; - now_read_line_begin = i; - break; - } - case H_KEY: - { - if (str[i] == ':') - { - key_end = i; - if (key_end - key_start <= 0) - return PARSE_HEADER_ERROR; - hState_ = H_COLON; - } - else if (str[i] == '\n' || str[i] == '\r') - return PARSE_HEADER_ERROR; - break; - } - case H_COLON: - { - if (str[i] == ' ') - { - hState_ = H_SPACES_AFTER_COLON; - } - else - return PARSE_HEADER_ERROR; - break; - } - case H_SPACES_AFTER_COLON: - { - hState_ = H_VALUE; - value_start = i; - break; - } - case H_VALUE: - { - if (str[i] == '\r') - { - hState_ = H_CR; - value_end = i; - if (value_end - value_start <= 0) - return PARSE_HEADER_ERROR; - } - else if (i - value_start > 255) - return PARSE_HEADER_ERROR; - break; - } - case H_CR: - { - if (str[i] == '\n') - { - hState_ = H_LF; - string key(str.begin() + key_start, str.begin() + key_end); - string value(str.begin() + value_start, str.begin() + value_end); - headers_[key] = value; - now_read_line_begin = i; - } - else - return PARSE_HEADER_ERROR; - break; - } - case H_LF: - { - if (str[i] == '\r') - { - hState_ = H_END_CR; - } - else - { - key_start = i; - hState_ = H_KEY; - } - break; - } - case H_END_CR: - { - if (str[i] == '\n') - { - hState_ = H_END_LF; - } - else - return PARSE_HEADER_ERROR; - break; - } - case H_END_LF: - { - notFinish = false; - key_start = i; - now_read_line_begin = i; - break; - } +HeaderState HttpData::parseHeaders() { + string &str = inBuffer_; + int key_start = -1, key_end = -1, value_start = -1, value_end = -1; + int now_read_line_begin = 0; + bool notFinish = true; + size_t i = 0; + for (; i < str.size() && notFinish; ++i) { + switch (hState_) { + case H_START: { + if (str[i] == '\n' || str[i] == '\r') break; + hState_ = H_KEY; + key_start = i; + now_read_line_begin = i; + break; + } + case H_KEY: { + if (str[i] == ':') { + key_end = i; + if (key_end - key_start <= 0) return PARSE_HEADER_ERROR; + hState_ = H_COLON; + } else if (str[i] == '\n' || str[i] == '\r') + return PARSE_HEADER_ERROR; + break; + } + case H_COLON: { + if (str[i] == ' ') { + hState_ = H_SPACES_AFTER_COLON; + } else + return PARSE_HEADER_ERROR; + break; + } + case H_SPACES_AFTER_COLON: { + hState_ = H_VALUE; + value_start = i; + break; + } + case H_VALUE: { + if (str[i] == '\r') { + hState_ = H_CR; + value_end = i; + if (value_end - value_start <= 0) return PARSE_HEADER_ERROR; + } else if (i - value_start > 255) + return PARSE_HEADER_ERROR; + break; + } + case H_CR: { + if (str[i] == '\n') { + hState_ = H_LF; + string key(str.begin() + key_start, str.begin() + key_end); + string value(str.begin() + value_start, str.begin() + value_end); + headers_[key] = value; + now_read_line_begin = i; + } else + return PARSE_HEADER_ERROR; + break; + } + case H_LF: { + if (str[i] == '\r') { + hState_ = H_END_CR; + } else { + key_start = i; + hState_ = H_KEY; } + break; + } + case H_END_CR: { + if (str[i] == '\n') { + hState_ = H_END_LF; + } else + return PARSE_HEADER_ERROR; + break; + } + case H_END_LF: { + notFinish = false; + key_start = i; + now_read_line_begin = i; + break; + } } - if (hState_ == H_END_LF) - { - str = str.substr(i); - return PARSE_HEADER_SUCCESS; - } - str = str.substr(now_read_line_begin); - return PARSE_HEADER_AGAIN; + } + if (hState_ == H_END_LF) { + str = str.substr(i); + return PARSE_HEADER_SUCCESS; + } + str = str.substr(now_read_line_begin); + return PARSE_HEADER_AGAIN; } -AnalysisState HttpData::analysisRequest() -{ - if (method_ == METHOD_POST) - { - // ------------------------------------------------------ - // My CV stitching handler which requires OpenCV library - // ------------------------------------------------------ - // string header; - // header += string("HTTP/1.1 200 OK\r\n"); - // if(headers_.find("Connection") != headers_.end() && headers_["Connection"] == "Keep-Alive") - // { - // keepAlive_ = true; - // header += string("Connection: Keep-Alive\r\n") + "Keep-Alive: timeout=" + to_string(DEFAULT_KEEP_ALIVE_TIME) + "\r\n"; - // } - // int length = stoi(headers_["Content-length"]); - // vector data(inBuffer_.begin(), inBuffer_.begin() + length); - // Mat src = imdecode(data, CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR); - // //imwrite("receive.bmp", src); - // Mat res = stitch(src); - // vector data_encode; - // imencode(".png", res, data_encode); - // header += string("Content-length: ") + to_string(data_encode.size()) + "\r\n\r\n"; - // outBuffer_ += header + string(data_encode.begin(), data_encode.end()); - // inBuffer_ = inBuffer_.substr(length); - // return ANALYSIS_SUCCESS; +AnalysisState HttpData::analysisRequest() { + if (method_ == METHOD_POST) { + // ------------------------------------------------------ + // My CV stitching handler which requires OpenCV library + // ------------------------------------------------------ + // string header; + // header += string("HTTP/1.1 200 OK\r\n"); + // if(headers_.find("Connection") != headers_.end() && + // headers_["Connection"] == "Keep-Alive") + // { + // keepAlive_ = true; + // header += string("Connection: Keep-Alive\r\n") + "Keep-Alive: + // timeout=" + to_string(DEFAULT_KEEP_ALIVE_TIME) + "\r\n"; + // } + // int length = stoi(headers_["Content-length"]); + // vector data(inBuffer_.begin(), inBuffer_.begin() + length); + // Mat src = imdecode(data, CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR); + // //imwrite("receive.bmp", src); + // Mat res = stitch(src); + // vector data_encode; + // imencode(".png", res, data_encode); + // header += string("Content-length: ") + to_string(data_encode.size()) + + // "\r\n\r\n"; + // outBuffer_ += header + string(data_encode.begin(), data_encode.end()); + // inBuffer_ = inBuffer_.substr(length); + // return ANALYSIS_SUCCESS; + } else if (method_ == METHOD_GET || method_ == METHOD_HEAD) { + string header; + header += "HTTP/1.1 200 OK\r\n"; + if (headers_.find("Connection") != headers_.end() && + (headers_["Connection"] == "Keep-Alive" || + headers_["Connection"] == "keep-alive")) { + keepAlive_ = true; + header += string("Connection: Keep-Alive\r\n") + "Keep-Alive: timeout=" + + to_string(DEFAULT_KEEP_ALIVE_TIME) + "\r\n"; } - else if (method_ == METHOD_GET || method_ == METHOD_HEAD) - { - string header; - header += "HTTP/1.1 200 OK\r\n"; - if(headers_.find("Connection") != headers_.end() && (headers_["Connection"] == "Keep-Alive" || headers_["Connection"] == "keep-alive")) - { - keepAlive_ = true; - header += string("Connection: Keep-Alive\r\n") + "Keep-Alive: timeout=" + to_string(DEFAULT_KEEP_ALIVE_TIME) + "\r\n"; - } - int dot_pos = fileName_.find('.'); - string filetype; - if (dot_pos < 0) - filetype = MimeType::getMime("default"); - else - filetype = MimeType::getMime(fileName_.substr(dot_pos)); - - - // echo test - if (fileName_ == "hello") - { - outBuffer_ = "HTTP/1.1 200 OK\r\nContent-type: text/plain\r\n\r\nHello World"; - return ANALYSIS_SUCCESS; - } - if (fileName_ == "favicon.ico") - { - header += "Content-Type: image/png\r\n"; - header += "Content-Length: " + to_string(sizeof favicon) + "\r\n"; - header += "Server: LinYa's Web Server\r\n"; - - header += "\r\n"; - outBuffer_ += header; - outBuffer_ += string(favicon, favicon + sizeof favicon);; - return ANALYSIS_SUCCESS; - } + int dot_pos = fileName_.find('.'); + string filetype; + if (dot_pos < 0) + filetype = MimeType::getMime("default"); + else + filetype = MimeType::getMime(fileName_.substr(dot_pos)); - struct stat sbuf; - if (stat(fileName_.c_str(), &sbuf) < 0) - { - header.clear(); - handleError(fd_, 404, "Not Found!"); - return ANALYSIS_ERROR; - } - header += "Content-Type: " + filetype + "\r\n"; - header += "Content-Length: " + to_string(sbuf.st_size) + "\r\n"; - header += "Server: LinYa's Web Server\r\n"; - // 头部结束 - header += "\r\n"; - outBuffer_ += header; - - if (method_ == METHOD_HEAD) - return ANALYSIS_SUCCESS; + // echo test + if (fileName_ == "hello") { + outBuffer_ = + "HTTP/1.1 200 OK\r\nContent-type: text/plain\r\n\r\nHello World"; + return ANALYSIS_SUCCESS; + } + if (fileName_ == "favicon.ico") { + header += "Content-Type: image/png\r\n"; + header += "Content-Length: " + to_string(sizeof favicon) + "\r\n"; + header += "Server: LinYa's Web Server\r\n"; + + header += "\r\n"; + outBuffer_ += header; + outBuffer_ += string(favicon, favicon + sizeof favicon); + ; + return ANALYSIS_SUCCESS; + } - int src_fd = open(fileName_.c_str(), O_RDONLY, 0); - if (src_fd < 0) - { - outBuffer_.clear(); - handleError(fd_, 404, "Not Found!"); - return ANALYSIS_ERROR; - } - void *mmapRet = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, src_fd, 0); - close(src_fd); - if (mmapRet == (void *)-1) - { - munmap(mmapRet, sbuf.st_size); - outBuffer_.clear(); - handleError(fd_, 404, "Not Found!"); - return ANALYSIS_ERROR; - } - char *src_addr = static_cast(mmapRet); - outBuffer_ += string(src_addr, src_addr + sbuf.st_size);; - munmap(mmapRet, sbuf.st_size); - return ANALYSIS_SUCCESS; + struct stat sbuf; + if (stat(fileName_.c_str(), &sbuf) < 0) { + header.clear(); + handleError(fd_, 404, "Not Found!"); + return ANALYSIS_ERROR; } - return ANALYSIS_ERROR; + header += "Content-Type: " + filetype + "\r\n"; + header += "Content-Length: " + to_string(sbuf.st_size) + "\r\n"; + header += "Server: LinYa's Web Server\r\n"; + // 头部结束 + header += "\r\n"; + outBuffer_ += header; + + if (method_ == METHOD_HEAD) return ANALYSIS_SUCCESS; + + int src_fd = open(fileName_.c_str(), O_RDONLY, 0); + if (src_fd < 0) { + outBuffer_.clear(); + handleError(fd_, 404, "Not Found!"); + return ANALYSIS_ERROR; + } + void *mmapRet = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, src_fd, 0); + close(src_fd); + if (mmapRet == (void *)-1) { + munmap(mmapRet, sbuf.st_size); + outBuffer_.clear(); + handleError(fd_, 404, "Not Found!"); + return ANALYSIS_ERROR; + } + char *src_addr = static_cast(mmapRet); + outBuffer_ += string(src_addr, src_addr + sbuf.st_size); + ; + munmap(mmapRet, sbuf.st_size); + return ANALYSIS_SUCCESS; + } + return ANALYSIS_ERROR; } -void HttpData::handleError(int fd, int err_num, string short_msg) -{ - short_msg = " " + short_msg; - char send_buff[4096]; - string body_buff, header_buff; - body_buff += "哎~出错了"; - body_buff += ""; - body_buff += to_string(err_num) + short_msg; - body_buff += "
LinYa's Web Server\n"; - - header_buff += "HTTP/1.1 " + to_string(err_num) + short_msg + "\r\n"; - header_buff += "Content-Type: text/html\r\n"; - header_buff += "Connection: Close\r\n"; - header_buff += "Content-Length: " + to_string(body_buff.size()) + "\r\n"; - header_buff += "Server: LinYa's Web Server\r\n";; - header_buff += "\r\n"; - // 错误处理不考虑writen不完的情况 - sprintf(send_buff, "%s", header_buff.c_str()); - writen(fd, send_buff, strlen(send_buff)); - sprintf(send_buff, "%s", body_buff.c_str()); - writen(fd, send_buff, strlen(send_buff)); +void HttpData::handleError(int fd, int err_num, string short_msg) { + short_msg = " " + short_msg; + char send_buff[4096]; + string body_buff, header_buff; + body_buff += "哎~出错了"; + body_buff += ""; + body_buff += to_string(err_num) + short_msg; + body_buff += "
LinYa's Web Server\n"; + + header_buff += "HTTP/1.1 " + to_string(err_num) + short_msg + "\r\n"; + header_buff += "Content-Type: text/html\r\n"; + header_buff += "Connection: Close\r\n"; + header_buff += "Content-Length: " + to_string(body_buff.size()) + "\r\n"; + header_buff += "Server: LinYa's Web Server\r\n"; + ; + header_buff += "\r\n"; + // 错误处理不考虑writen不完的情况 + sprintf(send_buff, "%s", header_buff.c_str()); + writen(fd, send_buff, strlen(send_buff)); + sprintf(send_buff, "%s", body_buff.c_str()); + writen(fd, send_buff, strlen(send_buff)); } -void HttpData::handleClose() -{ - connectionState_ = H_DISCONNECTED; - shared_ptr guard(shared_from_this()); - loop_->removeFromPoller(channel_); +void HttpData::handleClose() { + connectionState_ = H_DISCONNECTED; + shared_ptr guard(shared_from_this()); + loop_->removeFromPoller(channel_); } - -void HttpData::newEvent() -{ - channel_->setEvents(DEFAULT_EVENT); - loop_->addToPoller(channel_, DEFAULT_EXPIRED_TIME); +void HttpData::newEvent() { + channel_->setEvents(DEFAULT_EVENT); + loop_->addToPoller(channel_, DEFAULT_EXPIRED_TIME); } diff --git a/WebServer/HttpData.h b/WebServer/HttpData.h index 6a477b7..586c5c6 100755 --- a/WebServer/HttpData.h +++ b/WebServer/HttpData.h @@ -1,139 +1,114 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "Timer.h" -#include -#include -#include -#include #include -#include #include +#include +#include +#include +#include +#include +#include "Timer.h" + class EventLoop; class TimerNode; class Channel; -enum ProcessState -{ - STATE_PARSE_URI = 1, - STATE_PARSE_HEADERS, - STATE_RECV_BODY, - STATE_ANALYSIS, - STATE_FINISH +enum ProcessState { + STATE_PARSE_URI = 1, + STATE_PARSE_HEADERS, + STATE_RECV_BODY, + STATE_ANALYSIS, + STATE_FINISH }; -enum URIState -{ - PARSE_URI_AGAIN = 1, - PARSE_URI_ERROR, - PARSE_URI_SUCCESS, +enum URIState { + PARSE_URI_AGAIN = 1, + PARSE_URI_ERROR, + PARSE_URI_SUCCESS, }; -enum HeaderState -{ - PARSE_HEADER_SUCCESS = 1, - PARSE_HEADER_AGAIN, - PARSE_HEADER_ERROR +enum HeaderState { + PARSE_HEADER_SUCCESS = 1, + PARSE_HEADER_AGAIN, + PARSE_HEADER_ERROR }; -enum AnalysisState -{ - ANALYSIS_SUCCESS = 1, - ANALYSIS_ERROR +enum AnalysisState { ANALYSIS_SUCCESS = 1, ANALYSIS_ERROR }; + +enum ParseState { + H_START = 0, + H_KEY, + H_COLON, + H_SPACES_AFTER_COLON, + H_VALUE, + H_CR, + H_LF, + H_END_CR, + H_END_LF }; -enum ParseState -{ - H_START = 0, - H_KEY, - H_COLON, - H_SPACES_AFTER_COLON, - H_VALUE, - H_CR, - H_LF, - H_END_CR, - H_END_LF -}; +enum ConnectionState { H_CONNECTED = 0, H_DISCONNECTING, H_DISCONNECTED }; -enum ConnectionState -{ - H_CONNECTED = 0, - H_DISCONNECTING, - H_DISCONNECTED -}; +enum HttpMethod { METHOD_POST = 1, METHOD_GET, METHOD_HEAD }; -enum HttpMethod -{ - METHOD_POST = 1, - METHOD_GET, - METHOD_HEAD -}; - -enum HttpVersion -{ - HTTP_10 = 1, - HTTP_11 -}; +enum HttpVersion { HTTP_10 = 1, HTTP_11 }; -class MimeType -{ -private: - static void init(); - static std::unordered_map mime; - MimeType(); - MimeType(const MimeType &m); +class MimeType { + private: + static void init(); + static std::unordered_map mime; + MimeType(); + MimeType(const MimeType &m); -public: - static std::string getMime(const std::string &suffix); + public: + static std::string getMime(const std::string &suffix); -private: - static pthread_once_t once_control; + private: + static pthread_once_t once_control; }; - -class HttpData: public std::enable_shared_from_this -{ -public: - HttpData(EventLoop *loop, int connfd); - ~HttpData() { close(fd_); } - void reset(); - void seperateTimer(); - void linkTimer(std::shared_ptr mtimer) - { - // shared_ptr重载了bool, 但weak_ptr没有 - timer_ = mtimer; - } - std::shared_ptr getChannel() { return channel_; } - EventLoop *getLoop() { return loop_; } - void handleClose(); - void newEvent(); - -private: - EventLoop *loop_; - std::shared_ptr channel_; - int fd_; - std::string inBuffer_; - std::string outBuffer_; - bool error_; - ConnectionState connectionState_; - - HttpMethod method_; - HttpVersion HTTPVersion_; - std::string fileName_; - std::string path_; - int nowReadPos_; - ProcessState state_; - ParseState hState_; - bool keepAlive_; - std::map headers_; - std::weak_ptr timer_; - - void handleRead(); - void handleWrite(); - void handleConn(); - void handleError(int fd, int err_num, std::string short_msg); - URIState parseURI(); - HeaderState parseHeaders(); - AnalysisState analysisRequest(); +class HttpData : public std::enable_shared_from_this { + public: + HttpData(EventLoop *loop, int connfd); + ~HttpData() { close(fd_); } + void reset(); + void seperateTimer(); + void linkTimer(std::shared_ptr mtimer) { + // shared_ptr重载了bool, 但weak_ptr没有 + timer_ = mtimer; + } + std::shared_ptr getChannel() { return channel_; } + EventLoop *getLoop() { return loop_; } + void handleClose(); + void newEvent(); + + private: + EventLoop *loop_; + std::shared_ptr channel_; + int fd_; + std::string inBuffer_; + std::string outBuffer_; + bool error_; + ConnectionState connectionState_; + + HttpMethod method_; + HttpVersion HTTPVersion_; + std::string fileName_; + std::string path_; + int nowReadPos_; + ProcessState state_; + ParseState hState_; + bool keepAlive_; + std::map headers_; + std::weak_ptr timer_; + + void handleRead(); + void handleWrite(); + void handleConn(); + void handleError(int fd, int err_num, std::string short_msg); + URIState parseURI(); + HeaderState parseHeaders(); + AnalysisState analysisRequest(); }; \ No newline at end of file diff --git a/WebServer/Main.cpp b/WebServer/Main.cpp index 7668c6b..fc76799 100755 --- a/WebServer/Main.cpp +++ b/WebServer/Main.cpp @@ -1,55 +1,50 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com +#include +#include #include "EventLoop.h" #include "Server.h" #include "base/Logging.h" -#include -#include -int main(int argc, char *argv[]) -{ - int threadNum = 4; - int port = 80; - std::string logPath = "./WebServer.log"; - // parse args - int opt; - const char *str = "t:l:p:"; - while ((opt = getopt(argc, argv, str))!= -1) - { - switch (opt) - { - case 't': - { - threadNum = atoi(optarg); - break; - } - case 'l': - { - logPath = optarg; - if (logPath.size() < 2 || optarg[0] != '/') - { - printf("logPath should start with \"/\"\n"); - abort(); - } - break; - } - case 'p': - { - port = atoi(optarg); - break; - } - default: break; +int main(int argc, char *argv[]) { + int threadNum = 4; + int port = 80; + std::string logPath = "./WebServer.log"; + + // parse args + int opt; + const char *str = "t:l:p:"; + while ((opt = getopt(argc, argv, str)) != -1) { + switch (opt) { + case 't': { + threadNum = atoi(optarg); + break; + } + case 'l': { + logPath = optarg; + if (logPath.size() < 2 || optarg[0] != '/') { + printf("logPath should start with \"/\"\n"); + abort(); } + break; + } + case 'p': { + port = atoi(optarg); + break; + } + default: + break; } - Logger::setLogFileName(logPath); - // STL库在多线程上应用 - #ifndef _PTHREADS - LOG << "_PTHREADS is not defined !"; - #endif - EventLoop mainLoop; - Server myHTTPServer(&mainLoop, threadNum, port); - myHTTPServer.start(); - mainLoop.loop(); - return 0; + } + Logger::setLogFileName(logPath); +// STL库在多线程上应用 +#ifndef _PTHREADS + LOG << "_PTHREADS is not defined !"; +#endif + EventLoop mainLoop; + Server myHTTPServer(&mainLoop, threadNum, port); + myHTTPServer.start(); + mainLoop.loop(); + return 0; } diff --git a/WebServer/Server.cpp b/WebServer/Server.cpp index e0da461..5f39a95 100755 --- a/WebServer/Server.cpp +++ b/WebServer/Server.cpp @@ -1,83 +1,77 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "Server.h" -#include "base/Logging.h" -#include "Util.h" -#include +#include #include #include -#include - +#include +#include "Util.h" +#include "base/Logging.h" Server::Server(EventLoop *loop, int threadNum, int port) -: loop_(loop), - threadNum_(threadNum), - eventLoopThreadPool_(new EventLoopThreadPool(loop_, threadNum)), - started_(false), - acceptChannel_(new Channel(loop_)), - port_(port), - listenFd_(socket_bind_listen(port_)) -{ - acceptChannel_->setFd(listenFd_); - handle_for_sigpipe(); - if (setSocketNonBlocking(listenFd_) < 0) - { - perror("set socket non block failed"); - abort(); - } + : loop_(loop), + threadNum_(threadNum), + eventLoopThreadPool_(new EventLoopThreadPool(loop_, threadNum)), + started_(false), + acceptChannel_(new Channel(loop_)), + port_(port), + listenFd_(socket_bind_listen(port_)) { + acceptChannel_->setFd(listenFd_); + handle_for_sigpipe(); + if (setSocketNonBlocking(listenFd_) < 0) { + perror("set socket non block failed"); + abort(); + } } -void Server::start() -{ - eventLoopThreadPool_->start(); - //acceptChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); - acceptChannel_->setEvents(EPOLLIN | EPOLLET); - acceptChannel_->setReadHandler(bind(&Server::handNewConn, this)); - acceptChannel_->setConnHandler(bind(&Server::handThisConn, this)); - loop_->addToPoller(acceptChannel_, 0); - started_ = true; +void Server::start() { + eventLoopThreadPool_->start(); + // acceptChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); + acceptChannel_->setEvents(EPOLLIN | EPOLLET); + acceptChannel_->setReadHandler(bind(&Server::handNewConn, this)); + acceptChannel_->setConnHandler(bind(&Server::handThisConn, this)); + loop_->addToPoller(acceptChannel_, 0); + started_ = true; } -void Server::handNewConn() -{ - struct sockaddr_in client_addr; - memset(&client_addr, 0, sizeof(struct sockaddr_in)); - socklen_t client_addr_len = sizeof(client_addr); - int accept_fd = 0; - while((accept_fd = accept(listenFd_, (struct sockaddr*)&client_addr, &client_addr_len)) > 0) - { - EventLoop *loop = eventLoopThreadPool_->getNextLoop(); - LOG << "New connection from " << inet_ntoa(client_addr.sin_addr) << ":" << ntohs(client_addr.sin_port); - // cout << "new connection" << endl; - // cout << inet_ntoa(client_addr.sin_addr) << endl; - // cout << ntohs(client_addr.sin_port) << endl; - /* - // TCP的保活机制默认是关闭的 - int optval = 0; - socklen_t len_optval = 4; - getsockopt(accept_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, &len_optval); - cout << "optval ==" << optval << endl; - */ - // 限制服务器的最大并发连接数 - if (accept_fd >= MAXFDS) - { - close(accept_fd); - continue; - } - // 设为非阻塞模式 - if (setSocketNonBlocking(accept_fd) < 0) - { - LOG << "Set non block failed!"; - //perror("Set non block failed!"); - return; - } +void Server::handNewConn() { + struct sockaddr_in client_addr; + memset(&client_addr, 0, sizeof(struct sockaddr_in)); + socklen_t client_addr_len = sizeof(client_addr); + int accept_fd = 0; + while ((accept_fd = accept(listenFd_, (struct sockaddr *)&client_addr, + &client_addr_len)) > 0) { + EventLoop *loop = eventLoopThreadPool_->getNextLoop(); + LOG << "New connection from " << inet_ntoa(client_addr.sin_addr) << ":" + << ntohs(client_addr.sin_port); + // cout << "new connection" << endl; + // cout << inet_ntoa(client_addr.sin_addr) << endl; + // cout << ntohs(client_addr.sin_port) << endl; + /* + // TCP的保活机制默认是关闭的 + int optval = 0; + socklen_t len_optval = 4; + getsockopt(accept_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, &len_optval); + cout << "optval ==" << optval << endl; + */ + // 限制服务器的最大并发连接数 + if (accept_fd >= MAXFDS) { + close(accept_fd); + continue; + } + // 设为非阻塞模式 + if (setSocketNonBlocking(accept_fd) < 0) { + LOG << "Set non block failed!"; + // perror("Set non block failed!"); + return; + } - setSocketNodelay(accept_fd); - //setSocketNoLinger(accept_fd); + setSocketNodelay(accept_fd); + // setSocketNoLinger(accept_fd); - shared_ptr req_info(new HttpData(loop, accept_fd)); - req_info->getChannel()->setHolder(req_info); - loop->queueInLoop(std::bind(&HttpData::newEvent, req_info)); - } - acceptChannel_->setEvents(EPOLLIN | EPOLLET); + shared_ptr req_info(new HttpData(loop, accept_fd)); + req_info->getChannel()->setHolder(req_info); + loop->queueInLoop(std::bind(&HttpData::newEvent, req_info)); + } + acceptChannel_->setEvents(EPOLLIN | EPOLLET); } \ No newline at end of file diff --git a/WebServer/Server.h b/WebServer/Server.h index 0b84bbc..57f8f74 100755 --- a/WebServer/Server.h +++ b/WebServer/Server.h @@ -1,29 +1,27 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "EventLoop.h" +#include #include "Channel.h" +#include "EventLoop.h" #include "EventLoopThreadPool.h" -#include - -class Server -{ -public: - Server(EventLoop *loop, int threadNum, int port); - ~Server() { } - EventLoop* getLoop() const { return loop_; } - void start(); - void handNewConn(); - void handThisConn() { loop_->updatePoller(acceptChannel_); } +class Server { + public: + Server(EventLoop *loop, int threadNum, int port); + ~Server() {} + EventLoop *getLoop() const { return loop_; } + void start(); + void handNewConn(); + void handThisConn() { loop_->updatePoller(acceptChannel_); } -private: - EventLoop *loop_; - int threadNum_; - std::unique_ptr eventLoopThreadPool_; - bool started_; - std::shared_ptr acceptChannel_; - int port_; - int listenFd_; - static const int MAXFDS = 100000; + private: + EventLoop *loop_; + int threadNum_; + std::unique_ptr eventLoopThreadPool_; + bool started_; + std::shared_ptr acceptChannel_; + int port_; + int listenFd_; + static const int MAXFDS = 100000; }; \ No newline at end of file diff --git a/WebServer/Timer.cpp b/WebServer/Timer.cpp index 911cac0..f7df2a1 100755 --- a/WebServer/Timer.cpp +++ b/WebServer/Timer.cpp @@ -5,93 +5,78 @@ #include #include - TimerNode::TimerNode(std::shared_ptr requestData, int timeout) -: deleted_(false), - SPHttpData(requestData) -{ - struct timeval now; - gettimeofday(&now, NULL); - // 以毫秒计 - expiredTime_ = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout; + : deleted_(false), SPHttpData(requestData) { + struct timeval now; + gettimeofday(&now, NULL); + // 以毫秒计 + expiredTime_ = + (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout; } -TimerNode::~TimerNode() -{ - if (SPHttpData) - SPHttpData->handleClose(); +TimerNode::~TimerNode() { + if (SPHttpData) SPHttpData->handleClose(); } -TimerNode::TimerNode(TimerNode &tn): - SPHttpData(tn.SPHttpData), - expiredTime_(0) -{ } - - -void TimerNode::update(int timeout) -{ - struct timeval now; - gettimeofday(&now, NULL); - expiredTime_ = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout; -} +TimerNode::TimerNode(TimerNode &tn) + : SPHttpData(tn.SPHttpData), expiredTime_(0) {} -bool TimerNode::isValid() -{ - struct timeval now; - gettimeofday(&now, NULL); - size_t temp = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)); - if (temp < expiredTime_) - return true; - else - { - this->setDeleted(); - return false; - } +void TimerNode::update(int timeout) { + struct timeval now; + gettimeofday(&now, NULL); + expiredTime_ = + (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout; } -void TimerNode::clearReq() -{ - SPHttpData.reset(); +bool TimerNode::isValid() { + struct timeval now; + gettimeofday(&now, NULL); + size_t temp = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)); + if (temp < expiredTime_) + return true; + else { this->setDeleted(); + return false; + } } +void TimerNode::clearReq() { + SPHttpData.reset(); + this->setDeleted(); +} -TimerManager::TimerManager() -{ } +TimerManager::TimerManager() {} -TimerManager::~TimerManager() -{ } +TimerManager::~TimerManager() {} -void TimerManager::addTimer(std::shared_ptr SPHttpData, int timeout) -{ - SPTimerNode new_node(new TimerNode(SPHttpData, timeout)); - timerNodeQueue.push(new_node); - SPHttpData->linkTimer(new_node); +void TimerManager::addTimer(std::shared_ptr SPHttpData, int timeout) { + SPTimerNode new_node(new TimerNode(SPHttpData, timeout)); + timerNodeQueue.push(new_node); + SPHttpData->linkTimer(new_node); } - /* 处理逻辑是这样的~ 因为(1) 优先队列不支持随机访问 (2) 即使支持,随机删除某节点后破坏了堆的结构,需要重新更新堆结构。 -所以对于被置为deleted的时间节点,会延迟到它(1)超时 或 (2)它前面的节点都被删除时,它才会被删除。 +所以对于被置为deleted的时间节点,会延迟到它(1)超时 或 +(2)它前面的节点都被删除时,它才会被删除。 一个点被置为deleted,它最迟会在TIMER_TIME_OUT时间后被删除。 这样做有两个好处: (1) 第一个好处是不需要遍历优先队列,省时。 -(2) 第二个好处是给超时时间一个容忍的时间,就是设定的超时时间是删除的下限(并不是一到超时时间就立即删除),如果监听的请求在超时后的下一次请求中又一次出现了, +(2) +第二个好处是给超时时间一个容忍的时间,就是设定的超时时间是删除的下限(并不是一到超时时间就立即删除),如果监听的请求在超时后的下一次请求中又一次出现了, 就不用再重新申请RequestData节点了,这样可以继续重复利用前面的RequestData,减少了一次delete和一次new的时间。 */ -void TimerManager::handleExpiredEvent() -{ - //MutexLockGuard locker(lock); - while (!timerNodeQueue.empty()) - { - SPTimerNode ptimer_now = timerNodeQueue.top(); - if (ptimer_now->isDeleted()) - timerNodeQueue.pop(); - else if (ptimer_now->isValid() == false) - timerNodeQueue.pop(); - else - break; - } +void TimerManager::handleExpiredEvent() { + // MutexLockGuard locker(lock); + while (!timerNodeQueue.empty()) { + SPTimerNode ptimer_now = timerNodeQueue.top(); + if (ptimer_now->isDeleted()) + timerNodeQueue.pop(); + else if (ptimer_now->isValid() == false) + timerNodeQueue.pop(); + else + break; + } } \ No newline at end of file diff --git a/WebServer/Timer.h b/WebServer/Timer.h index 1c91c57..f0dacaf 100755 --- a/WebServer/Timer.h +++ b/WebServer/Timer.h @@ -1,53 +1,52 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "HttpData.h" -#include "base/noncopyable.h" -#include "base/MutexLock.h" #include +#include #include #include -#include +#include "HttpData.h" +#include "base/MutexLock.h" +#include "base/noncopyable.h" + class HttpData; -class TimerNode -{ -public: - TimerNode(std::shared_ptr requestData, int timeout); - ~TimerNode(); - TimerNode(TimerNode &tn); - void update(int timeout); - bool isValid(); - void clearReq(); - void setDeleted() { deleted_ = true; } - bool isDeleted() const { return deleted_; } - size_t getExpTime() const { return expiredTime_; } +class TimerNode { + public: + TimerNode(std::shared_ptr requestData, int timeout); + ~TimerNode(); + TimerNode(TimerNode &tn); + void update(int timeout); + bool isValid(); + void clearReq(); + void setDeleted() { deleted_ = true; } + bool isDeleted() const { return deleted_; } + size_t getExpTime() const { return expiredTime_; } -private: - bool deleted_; - size_t expiredTime_; - std::shared_ptr SPHttpData; + private: + bool deleted_; + size_t expiredTime_; + std::shared_ptr SPHttpData; }; -struct TimerCmp -{ - bool operator()(std::shared_ptr &a, std::shared_ptr &b) const - { - return a->getExpTime() > b->getExpTime(); - } +struct TimerCmp { + bool operator()(std::shared_ptr &a, + std::shared_ptr &b) const { + return a->getExpTime() > b->getExpTime(); + } }; -class TimerManager -{ -public: - TimerManager(); - ~TimerManager(); - void addTimer(std::shared_ptr SPHttpData, int timeout); - void handleExpiredEvent(); +class TimerManager { + public: + TimerManager(); + ~TimerManager(); + void addTimer(std::shared_ptr SPHttpData, int timeout); + void handleExpiredEvent(); -private: - typedef std::shared_ptr SPTimerNode; - std::priority_queue, TimerCmp> timerNodeQueue; - //MutexLock lock; + private: + typedef std::shared_ptr SPTimerNode; + std::priority_queue, TimerCmp> + timerNodeQueue; + // MutexLock lock; }; \ No newline at end of file diff --git a/WebServer/Util.cpp b/WebServer/Util.cpp index 4bbd469..8822d4c 100755 --- a/WebServer/Util.cpp +++ b/WebServer/Util.cpp @@ -1,272 +1,223 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "Util.h" -#include + +#include #include +#include +#include #include -#include #include #include -#include -#include +#include + const int MAX_BUFF = 4096; -ssize_t readn(int fd, void *buff, size_t n) -{ - size_t nleft = n; - ssize_t nread = 0; - ssize_t readSum = 0; - char *ptr = (char*)buff; - while (nleft > 0) - { - if ((nread = read(fd, ptr, nleft)) < 0) - { - if (errno == EINTR) - nread = 0; - else if (errno == EAGAIN) - { - return readSum; - } - else - { - return -1; - } - } - else if (nread == 0) - break; - readSum += nread; - nleft -= nread; - ptr += nread; - } - return readSum; +ssize_t readn(int fd, void *buff, size_t n) { + size_t nleft = n; + ssize_t nread = 0; + ssize_t readSum = 0; + char *ptr = (char *)buff; + while (nleft > 0) { + if ((nread = read(fd, ptr, nleft)) < 0) { + if (errno == EINTR) + nread = 0; + else if (errno == EAGAIN) { + return readSum; + } else { + return -1; + } + } else if (nread == 0) + break; + readSum += nread; + nleft -= nread; + ptr += nread; + } + return readSum; } -ssize_t readn(int fd, std::string &inBuffer, bool &zero) -{ - ssize_t nread = 0; - ssize_t readSum = 0; - while (true) - { - char buff[MAX_BUFF]; - if ((nread = read(fd, buff, MAX_BUFF)) < 0) - { - if (errno == EINTR) - continue; - else if (errno == EAGAIN) - { - return readSum; - } - else - { - perror("read error"); - return -1; - } - } - else if (nread == 0) - { - //printf("redsum = %d\n", readSum); - zero = true; - break; - } - //printf("before inBuffer.size() = %d\n", inBuffer.size()); - //printf("nread = %d\n", nread); - readSum += nread; - //buff += nread; - inBuffer += std::string(buff, buff + nread); - //printf("after inBuffer.size() = %d\n", inBuffer.size()); +ssize_t readn(int fd, std::string &inBuffer, bool &zero) { + ssize_t nread = 0; + ssize_t readSum = 0; + while (true) { + char buff[MAX_BUFF]; + if ((nread = read(fd, buff, MAX_BUFF)) < 0) { + if (errno == EINTR) + continue; + else if (errno == EAGAIN) { + return readSum; + } else { + perror("read error"); + return -1; + } + } else if (nread == 0) { + // printf("redsum = %d\n", readSum); + zero = true; + break; } - return readSum; + // printf("before inBuffer.size() = %d\n", inBuffer.size()); + // printf("nread = %d\n", nread); + readSum += nread; + // buff += nread; + inBuffer += std::string(buff, buff + nread); + // printf("after inBuffer.size() = %d\n", inBuffer.size()); + } + return readSum; } - -ssize_t readn(int fd, std::string &inBuffer) -{ - ssize_t nread = 0; - ssize_t readSum = 0; - while (true) - { - char buff[MAX_BUFF]; - if ((nread = read(fd, buff, MAX_BUFF)) < 0) - { - if (errno == EINTR) - continue; - else if (errno == EAGAIN) - { - return readSum; - } - else - { - perror("read error"); - return -1; - } - } - else if (nread == 0) - { - //printf("redsum = %d\n", readSum); - break; - } - //printf("before inBuffer.size() = %d\n", inBuffer.size()); - //printf("nread = %d\n", nread); - readSum += nread; - //buff += nread; - inBuffer += std::string(buff, buff + nread); - //printf("after inBuffer.size() = %d\n", inBuffer.size()); +ssize_t readn(int fd, std::string &inBuffer) { + ssize_t nread = 0; + ssize_t readSum = 0; + while (true) { + char buff[MAX_BUFF]; + if ((nread = read(fd, buff, MAX_BUFF)) < 0) { + if (errno == EINTR) + continue; + else if (errno == EAGAIN) { + return readSum; + } else { + perror("read error"); + return -1; + } + } else if (nread == 0) { + // printf("redsum = %d\n", readSum); + break; } - return readSum; + // printf("before inBuffer.size() = %d\n", inBuffer.size()); + // printf("nread = %d\n", nread); + readSum += nread; + // buff += nread; + inBuffer += std::string(buff, buff + nread); + // printf("after inBuffer.size() = %d\n", inBuffer.size()); + } + return readSum; } - -ssize_t writen(int fd, void *buff, size_t n) -{ - size_t nleft = n; - ssize_t nwritten = 0; - ssize_t writeSum = 0; - char *ptr = (char*)buff; - while (nleft > 0) - { - if ((nwritten = write(fd, ptr, nleft)) <= 0) - { - if (nwritten < 0) - { - if (errno == EINTR) - { - nwritten = 0; - continue; - } - else if (errno == EAGAIN) - { - return writeSum; - } - else - return -1; - } - } - writeSum += nwritten; - nleft -= nwritten; - ptr += nwritten; +ssize_t writen(int fd, void *buff, size_t n) { + size_t nleft = n; + ssize_t nwritten = 0; + ssize_t writeSum = 0; + char *ptr = (char *)buff; + while (nleft > 0) { + if ((nwritten = write(fd, ptr, nleft)) <= 0) { + if (nwritten < 0) { + if (errno == EINTR) { + nwritten = 0; + continue; + } else if (errno == EAGAIN) { + return writeSum; + } else + return -1; + } } - return writeSum; + writeSum += nwritten; + nleft -= nwritten; + ptr += nwritten; + } + return writeSum; } -ssize_t writen(int fd, std::string &sbuff) -{ - size_t nleft = sbuff.size(); - ssize_t nwritten = 0; - ssize_t writeSum = 0; - const char *ptr = sbuff.c_str(); - while (nleft > 0) - { - if ((nwritten = write(fd, ptr, nleft)) <= 0) - { - if (nwritten < 0) - { - if (errno == EINTR) - { - nwritten = 0; - continue; - } - else if (errno == EAGAIN) - break; - else - return -1; - } - } - writeSum += nwritten; - nleft -= nwritten; - ptr += nwritten; +ssize_t writen(int fd, std::string &sbuff) { + size_t nleft = sbuff.size(); + ssize_t nwritten = 0; + ssize_t writeSum = 0; + const char *ptr = sbuff.c_str(); + while (nleft > 0) { + if ((nwritten = write(fd, ptr, nleft)) <= 0) { + if (nwritten < 0) { + if (errno == EINTR) { + nwritten = 0; + continue; + } else if (errno == EAGAIN) + break; + else + return -1; + } } - if (writeSum == static_cast(sbuff.size())) - sbuff.clear(); - else - sbuff = sbuff.substr(writeSum); - return writeSum; + writeSum += nwritten; + nleft -= nwritten; + ptr += nwritten; + } + if (writeSum == static_cast(sbuff.size())) + sbuff.clear(); + else + sbuff = sbuff.substr(writeSum); + return writeSum; } -void handle_for_sigpipe() -{ - struct sigaction sa; - memset(&sa, '\0', sizeof(sa)); - sa.sa_handler = SIG_IGN; - sa.sa_flags = 0; - if(sigaction(SIGPIPE, &sa, NULL)) - return; +void handle_for_sigpipe() { + struct sigaction sa; + memset(&sa, '\0', sizeof(sa)); + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + if (sigaction(SIGPIPE, &sa, NULL)) return; } -int setSocketNonBlocking(int fd) -{ - int flag = fcntl(fd, F_GETFL, 0); - if(flag == -1) - return -1; +int setSocketNonBlocking(int fd) { + int flag = fcntl(fd, F_GETFL, 0); + if (flag == -1) return -1; - flag |= O_NONBLOCK; - if(fcntl(fd, F_SETFL, flag) == -1) - return -1; - return 0; + flag |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, flag) == -1) return -1; + return 0; } -void setSocketNodelay(int fd) -{ - int enable = 1; - setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)); +void setSocketNodelay(int fd) { + int enable = 1; + setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&enable, sizeof(enable)); } -void setSocketNoLinger(int fd) -{ - struct linger linger_; - linger_.l_onoff = 1; - linger_.l_linger = 30; - setsockopt(fd, SOL_SOCKET, SO_LINGER,(const char *) &linger_, sizeof(linger_)); +void setSocketNoLinger(int fd) { + struct linger linger_; + linger_.l_onoff = 1; + linger_.l_linger = 30; + setsockopt(fd, SOL_SOCKET, SO_LINGER, (const char *)&linger_, + sizeof(linger_)); } -void shutDownWR(int fd) -{ - shutdown(fd, SHUT_WR); - //printf("shutdown\n"); +void shutDownWR(int fd) { + shutdown(fd, SHUT_WR); + // printf("shutdown\n"); } -int socket_bind_listen(int port) -{ - // 检查port值,取正确区间范围 - if (port < 0 || port > 65535) - return -1; - - // 创建socket(IPv4 + TCP),返回监听描述符 - int listen_fd = 0; - if((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) - return -1; - - // 消除bind时"Address already in use"错误 - int optval = 1; - if(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) - { - close(listen_fd); - return -1; - } - - // 设置服务器IP和Port,和监听描述副绑定 - struct sockaddr_in server_addr; - bzero((char*)&server_addr, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = htonl(INADDR_ANY); - server_addr.sin_port = htons((unsigned short)port); - if(bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) - { - close(listen_fd); - return -1; - } - - // 开始监听,最大等待队列长为LISTENQ - if(listen(listen_fd, 2048) == -1) - { - close(listen_fd); - return -1; - } - - // 无效监听描述符 - if(listen_fd == -1) - { - close(listen_fd); - return -1; - } - return listen_fd; +int socket_bind_listen(int port) { + // 检查port值,取正确区间范围 + if (port < 0 || port > 65535) return -1; + + // 创建socket(IPv4 + TCP),返回监听描述符 + int listen_fd = 0; + if ((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) return -1; + + // 消除bind时"Address already in use"错误 + int optval = 1; + if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &optval, + sizeof(optval)) == -1) { + close(listen_fd); + return -1; + } + + // 设置服务器IP和Port,和监听描述副绑定 + struct sockaddr_in server_addr; + bzero((char *)&server_addr, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + server_addr.sin_port = htons((unsigned short)port); + if (bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == + -1) { + close(listen_fd); + return -1; + } + + // 开始监听,最大等待队列长为LISTENQ + if (listen(listen_fd, 2048) == -1) { + close(listen_fd); + return -1; + } + + // 无效监听描述符 + if (listen_fd == -1) { + close(listen_fd); + return -1; + } + return listen_fd; } \ No newline at end of file diff --git a/WebServer/base/AsyncLogging.cpp b/WebServer/base/AsyncLogging.cpp index b37d300..69f3483 100755 --- a/WebServer/base/AsyncLogging.cpp +++ b/WebServer/base/AsyncLogging.cpp @@ -1,126 +1,115 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "AsyncLogging.h" -#include "LogFile.h" -#include #include +#include #include #include +#include "LogFile.h" - -AsyncLogging::AsyncLogging(std::string logFileName_,int flushInterval) - : flushInterval_(flushInterval), - running_(false), - basename_(logFileName_), - thread_(std::bind(&AsyncLogging::threadFunc, this), "Logging"), - mutex_(), - cond_(mutex_), - currentBuffer_(new Buffer), - nextBuffer_(new Buffer), - buffers_(), - latch_(1) -{ - assert(logFileName_.size() > 1); - currentBuffer_->bzero(); - nextBuffer_->bzero(); - buffers_.reserve(16); +AsyncLogging::AsyncLogging(std::string logFileName_, int flushInterval) + : flushInterval_(flushInterval), + running_(false), + basename_(logFileName_), + thread_(std::bind(&AsyncLogging::threadFunc, this), "Logging"), + mutex_(), + cond_(mutex_), + currentBuffer_(new Buffer), + nextBuffer_(new Buffer), + buffers_(), + latch_(1) { + assert(logFileName_.size() > 1); + currentBuffer_->bzero(); + nextBuffer_->bzero(); + buffers_.reserve(16); } -void AsyncLogging::append(const char* logline, int len) -{ - MutexLockGuard lock(mutex_); - if (currentBuffer_->avail() > len) - currentBuffer_->append(logline, len); +void AsyncLogging::append(const char* logline, int len) { + MutexLockGuard lock(mutex_); + if (currentBuffer_->avail() > len) + currentBuffer_->append(logline, len); + else { + buffers_.push_back(currentBuffer_); + currentBuffer_.reset(); + if (nextBuffer_) + currentBuffer_ = std::move(nextBuffer_); else - { - buffers_.push_back(currentBuffer_); - currentBuffer_.reset(); - if (nextBuffer_) - currentBuffer_ = std::move(nextBuffer_); - else - currentBuffer_.reset(new Buffer); - currentBuffer_->append(logline, len); - cond_.notify(); - } + currentBuffer_.reset(new Buffer); + currentBuffer_->append(logline, len); + cond_.notify(); + } } -void AsyncLogging::threadFunc() -{ - assert(running_ == true); - latch_.countDown(); - LogFile output(basename_); - BufferPtr newBuffer1(new Buffer); - BufferPtr newBuffer2(new Buffer); - newBuffer1->bzero(); - newBuffer2->bzero(); - BufferVector buffersToWrite; - buffersToWrite.reserve(16); - while (running_) - { - assert(newBuffer1 && newBuffer1->length() == 0); - assert(newBuffer2 && newBuffer2->length() == 0); - assert(buffersToWrite.empty()); - - { - MutexLockGuard lock(mutex_); - if (buffers_.empty()) // unusual usage! - { - cond_.waitForSeconds(flushInterval_); - } - buffers_.push_back(currentBuffer_); - currentBuffer_.reset(); +void AsyncLogging::threadFunc() { + assert(running_ == true); + latch_.countDown(); + LogFile output(basename_); + BufferPtr newBuffer1(new Buffer); + BufferPtr newBuffer2(new Buffer); + newBuffer1->bzero(); + newBuffer2->bzero(); + BufferVector buffersToWrite; + buffersToWrite.reserve(16); + while (running_) { + assert(newBuffer1 && newBuffer1->length() == 0); + assert(newBuffer2 && newBuffer2->length() == 0); + assert(buffersToWrite.empty()); - currentBuffer_ = std::move(newBuffer1); - buffersToWrite.swap(buffers_); - if (!nextBuffer_) - { - nextBuffer_ = std::move(newBuffer2); - } - } + { + MutexLockGuard lock(mutex_); + if (buffers_.empty()) // unusual usage! + { + cond_.waitForSeconds(flushInterval_); + } + buffers_.push_back(currentBuffer_); + currentBuffer_.reset(); - assert(!buffersToWrite.empty()); + currentBuffer_ = std::move(newBuffer1); + buffersToWrite.swap(buffers_); + if (!nextBuffer_) { + nextBuffer_ = std::move(newBuffer2); + } + } - if (buffersToWrite.size() > 25) - { - //char buf[256]; - // snprintf(buf, sizeof buf, "Dropped log messages at %s, %zd larger buffers\n", - // Timestamp::now().toFormattedString().c_str(), - // buffersToWrite.size()-2); - //fputs(buf, stderr); - //output.append(buf, static_cast(strlen(buf))); - buffersToWrite.erase(buffersToWrite.begin()+2, buffersToWrite.end()); - } + assert(!buffersToWrite.empty()); - for (size_t i = 0; i < buffersToWrite.size(); ++i) - { - // FIXME: use unbuffered stdio FILE ? or use ::writev ? - output.append(buffersToWrite[i]->data(), buffersToWrite[i]->length()); - } + if (buffersToWrite.size() > 25) { + // char buf[256]; + // snprintf(buf, sizeof buf, "Dropped log messages at %s, %zd larger + // buffers\n", + // Timestamp::now().toFormattedString().c_str(), + // buffersToWrite.size()-2); + // fputs(buf, stderr); + // output.append(buf, static_cast(strlen(buf))); + buffersToWrite.erase(buffersToWrite.begin() + 2, buffersToWrite.end()); + } - if (buffersToWrite.size() > 2) - { - // drop non-bzero-ed buffers, avoid trashing - buffersToWrite.resize(2); - } + for (size_t i = 0; i < buffersToWrite.size(); ++i) { + // FIXME: use unbuffered stdio FILE ? or use ::writev ? + output.append(buffersToWrite[i]->data(), buffersToWrite[i]->length()); + } - if (!newBuffer1) - { - assert(!buffersToWrite.empty()); - newBuffer1 = buffersToWrite.back(); - buffersToWrite.pop_back(); - newBuffer1->reset(); - } + if (buffersToWrite.size() > 2) { + // drop non-bzero-ed buffers, avoid trashing + buffersToWrite.resize(2); + } - if (!newBuffer2) - { - assert(!buffersToWrite.empty()); - newBuffer2 = buffersToWrite.back(); - buffersToWrite.pop_back(); - newBuffer2->reset(); - } + if (!newBuffer1) { + assert(!buffersToWrite.empty()); + newBuffer1 = buffersToWrite.back(); + buffersToWrite.pop_back(); + newBuffer1->reset(); + } - buffersToWrite.clear(); - output.flush(); + if (!newBuffer2) { + assert(!buffersToWrite.empty()); + newBuffer2 = buffersToWrite.back(); + buffersToWrite.pop_back(); + newBuffer2->reset(); } + + buffersToWrite.clear(); output.flush(); + } + output.flush(); } diff --git a/WebServer/base/AsyncLogging.h b/WebServer/base/AsyncLogging.h index cf8c928..534e7ef 100755 --- a/WebServer/base/AsyncLogging.h +++ b/WebServer/base/AsyncLogging.h @@ -1,54 +1,49 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once +#include +#include +#include #include "CountDownLatch.h" +#include "LogStream.h" #include "MutexLock.h" #include "Thread.h" -#include "LogStream.h" #include "noncopyable.h" -#include -#include -#include -class AsyncLogging : noncopyable -{ -public: - AsyncLogging(const std::string basename, int flushInterval = 2); - ~AsyncLogging() - { - if (running_) - stop(); - } - void append(const char* logline, int len); - void start() - { - running_ = true; - thread_.start(); - latch_.wait(); - } +class AsyncLogging : noncopyable { + public: + AsyncLogging(const std::string basename, int flushInterval = 2); + ~AsyncLogging() { + if (running_) stop(); + } + void append(const char* logline, int len); - void stop() - { - running_ = false; - cond_.notify(); - thread_.join(); - } + void start() { + running_ = true; + thread_.start(); + latch_.wait(); + } + void stop() { + running_ = false; + cond_.notify(); + thread_.join(); + } -private: - void threadFunc(); - typedef FixedBuffer Buffer; - typedef std::vector> BufferVector; - typedef std::shared_ptr BufferPtr; - const int flushInterval_; - bool running_; - std::string basename_; - Thread thread_; - MutexLock mutex_; - Condition cond_; - BufferPtr currentBuffer_; - BufferPtr nextBuffer_; - BufferVector buffers_; - CountDownLatch latch_; + private: + void threadFunc(); + typedef FixedBuffer Buffer; + typedef std::vector> BufferVector; + typedef std::shared_ptr BufferPtr; + const int flushInterval_; + bool running_; + std::string basename_; + Thread thread_; + MutexLock mutex_; + Condition cond_; + BufferPtr currentBuffer_; + BufferPtr nextBuffer_; + BufferVector buffers_; + CountDownLatch latch_; }; \ No newline at end of file diff --git a/WebServer/base/Condition.h b/WebServer/base/Condition.h index e216947..af298b5 100755 --- a/WebServer/base/Condition.h +++ b/WebServer/base/Condition.h @@ -1,46 +1,32 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "noncopyable.h" -#include "MutexLock.h" +#include #include #include -#include -#include #include +#include +#include "MutexLock.h" +#include "noncopyable.h" + + +class Condition : noncopyable { + public: + explicit Condition(MutexLock &_mutex) : mutex(_mutex) { + pthread_cond_init(&cond, NULL); + } + ~Condition() { pthread_cond_destroy(&cond); } + void wait() { pthread_cond_wait(&cond, mutex.get()); } + void notify() { pthread_cond_signal(&cond); } + void notifyAll() { pthread_cond_broadcast(&cond); } + bool waitForSeconds(int seconds) { + struct timespec abstime; + clock_gettime(CLOCK_REALTIME, &abstime); + abstime.tv_sec += static_cast(seconds); + return ETIMEDOUT == pthread_cond_timedwait(&cond, mutex.get(), &abstime); + } -class Condition: noncopyable -{ -public: - explicit Condition(MutexLock &_mutex): - mutex(_mutex) - { - pthread_cond_init(&cond, NULL); - } - ~Condition() - { - pthread_cond_destroy(&cond); - } - void wait() - { - pthread_cond_wait(&cond, mutex.get()); - } - void notify() - { - pthread_cond_signal(&cond); - } - void notifyAll() - { - pthread_cond_broadcast(&cond); - } - bool waitForSeconds(int seconds) - { - struct timespec abstime; - clock_gettime(CLOCK_REALTIME, &abstime); - abstime.tv_sec += static_cast(seconds); - return ETIMEDOUT == pthread_cond_timedwait(&cond, mutex.get(), &abstime); - } -private: - MutexLock &mutex; - pthread_cond_t cond; + private: + MutexLock &mutex; + pthread_cond_t cond; }; \ No newline at end of file diff --git a/WebServer/base/CountDownLatch.cpp b/WebServer/base/CountDownLatch.cpp index 2594d0c..638bc9a 100755 --- a/WebServer/base/CountDownLatch.cpp +++ b/WebServer/base/CountDownLatch.cpp @@ -3,22 +3,15 @@ #include "CountDownLatch.h" CountDownLatch::CountDownLatch(int count) - : mutex_(), - condition_(mutex_), - count_(count) -{ } + : mutex_(), condition_(mutex_), count_(count) {} -void CountDownLatch::wait() -{ - MutexLockGuard lock(mutex_); - while (count_ > 0) - condition_.wait(); +void CountDownLatch::wait() { + MutexLockGuard lock(mutex_); + while (count_ > 0) condition_.wait(); } -void CountDownLatch::countDown() -{ - MutexLockGuard lock(mutex_); - --count_; - if (count_ == 0) - condition_.notifyAll(); +void CountDownLatch::countDown() { + MutexLockGuard lock(mutex_); + --count_; + if (count_ == 0) condition_.notifyAll(); } \ No newline at end of file diff --git a/WebServer/base/CountDownLatch.h b/WebServer/base/CountDownLatch.h index 861a664..f8beedf 100755 --- a/WebServer/base/CountDownLatch.h +++ b/WebServer/base/CountDownLatch.h @@ -7,15 +7,14 @@ // CountDownLatch的主要作用是确保Thread中传进去的func真的启动了以后 // 外层的start才返回 -class CountDownLatch : noncopyable -{ -public: - explicit CountDownLatch(int count); - void wait(); - void countDown(); +class CountDownLatch : noncopyable { + public: + explicit CountDownLatch(int count); + void wait(); + void countDown(); -private: - mutable MutexLock mutex_; - Condition condition_; - int count_; + private: + mutable MutexLock mutex_; + Condition condition_; + int count_; }; \ No newline at end of file diff --git a/WebServer/base/CurrentThread.h b/WebServer/base/CurrentThread.h index b02d583..61f02dc 100755 --- a/WebServer/base/CurrentThread.h +++ b/WebServer/base/CurrentThread.h @@ -3,37 +3,29 @@ #pragma once #include +namespace CurrentThread { +// internal +extern __thread int t_cachedTid; +extern __thread char t_tidString[32]; +extern __thread int t_tidStringLength; +extern __thread const char* t_threadName; +void cacheTid(); +inline int tid() { + if (__builtin_expect(t_cachedTid == 0, 0)) { + cacheTid(); + } + return t_cachedTid; +} -namespace CurrentThread +inline const char* tidString() // for logging { - // internal - extern __thread int t_cachedTid; - extern __thread char t_tidString[32]; - extern __thread int t_tidStringLength; - extern __thread const char* t_threadName; - void cacheTid(); - inline int tid() - { - if (__builtin_expect(t_cachedTid == 0, 0)) - { - cacheTid(); - } - return t_cachedTid; - } - - inline const char* tidString() // for logging - { - return t_tidString; - } - - inline int tidStringLength() // for logging - { - return t_tidStringLength; - } + return t_tidString; +} - inline const char* name() - { - return t_threadName; - } +inline int tidStringLength() // for logging +{ + return t_tidStringLength; } +inline const char* name() { return t_threadName; } +} diff --git a/WebServer/base/FileUtil.cpp b/WebServer/base/FileUtil.cpp index a8abadc..6963038 100755 --- a/WebServer/base/FileUtil.cpp +++ b/WebServer/base/FileUtil.cpp @@ -10,43 +10,30 @@ using namespace std; -AppendFile::AppendFile(string filename) -: fp_(fopen(filename.c_str(), "ae")) -{ - // 用户提供缓冲区 - setbuffer(fp_, buffer_, sizeof buffer_); +AppendFile::AppendFile(string filename) : fp_(fopen(filename.c_str(), "ae")) { + // 用户提供缓冲区 + setbuffer(fp_, buffer_, sizeof buffer_); } -AppendFile::~AppendFile() -{ - fclose(fp_); -} +AppendFile::~AppendFile() { fclose(fp_); } -void AppendFile::append(const char* logline, const size_t len) -{ - size_t n = this->write(logline, len); - size_t remain = len - n; - while (remain > 0) - { - size_t x = this->write(logline + n, remain); - if (x == 0) - { - int err = ferror(fp_); - if (err) - fprintf(stderr, "AppendFile::append() failed !\n"); - break; - } - n += x; - remain = len - n; +void AppendFile::append(const char* logline, const size_t len) { + size_t n = this->write(logline, len); + size_t remain = len - n; + while (remain > 0) { + size_t x = this->write(logline + n, remain); + if (x == 0) { + int err = ferror(fp_); + if (err) fprintf(stderr, "AppendFile::append() failed !\n"); + break; } + n += x; + remain = len - n; + } } -void AppendFile::flush() -{ - fflush(fp_); -} +void AppendFile::flush() { fflush(fp_); } -size_t AppendFile::write(const char* logline, size_t len) -{ - return fwrite_unlocked(logline, 1, len, fp_); +size_t AppendFile::write(const char* logline, size_t len) { + return fwrite_unlocked(logline, 1, len, fp_); } \ No newline at end of file diff --git a/WebServer/base/FileUtil.h b/WebServer/base/FileUtil.h index 04f4362..e6ff568 100755 --- a/WebServer/base/FileUtil.h +++ b/WebServer/base/FileUtil.h @@ -1,20 +1,20 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "noncopyable.h" #include +#include "noncopyable.h" + -class AppendFile : noncopyable -{ -public: - explicit AppendFile(std::string filename); - ~AppendFile(); - // append 会向文件写 - void append(const char *logline, const size_t len); - void flush(); +class AppendFile : noncopyable { + public: + explicit AppendFile(std::string filename); + ~AppendFile(); + // append 会向文件写 + void append(const char *logline, const size_t len); + void flush(); -private: - size_t write(const char *logline, size_t len); - FILE* fp_; - char buffer_[64*1024]; + private: + size_t write(const char *logline, size_t len); + FILE *fp_; + char buffer_[64 * 1024]; }; \ No newline at end of file diff --git a/WebServer/base/LogFile.cpp b/WebServer/base/LogFile.cpp index 15e8027..9ab7ca7 100755 --- a/WebServer/base/LogFile.cpp +++ b/WebServer/base/LogFile.cpp @@ -1,46 +1,40 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "LogFile.h" -#include "FileUtil.h" #include #include #include +#include "FileUtil.h" -using namespace std; +using namespace std; LogFile::LogFile(const string& basename, int flushEveryN) - : basename_(basename), - flushEveryN_(flushEveryN), - count_(0), - mutex_(new MutexLock) -{ - //assert(basename.find('/') >= 0); - file_.reset(new AppendFile(basename)); + : basename_(basename), + flushEveryN_(flushEveryN), + count_(0), + mutex_(new MutexLock) { + // assert(basename.find('/') >= 0); + file_.reset(new AppendFile(basename)); } -LogFile::~LogFile() -{ } +LogFile::~LogFile() {} -void LogFile::append(const char* logline, int len) -{ - MutexLockGuard lock(*mutex_); - append_unlocked(logline, len); +void LogFile::append(const char* logline, int len) { + MutexLockGuard lock(*mutex_); + append_unlocked(logline, len); } -void LogFile::flush() -{ - MutexLockGuard lock(*mutex_); - file_->flush(); +void LogFile::flush() { + MutexLockGuard lock(*mutex_); + file_->flush(); } -void LogFile::append_unlocked(const char* logline, int len) -{ - file_->append(logline, len); - ++count_; - if (count_ >= flushEveryN_) - { - count_ = 0; - file_->flush(); - } +void LogFile::append_unlocked(const char* logline, int len) { + file_->append(logline, len); + ++count_; + if (count_ >= flushEveryN_) { + count_ = 0; + file_->flush(); + } } \ No newline at end of file diff --git a/WebServer/base/LogFile.h b/WebServer/base/LogFile.h index cfdd927..ec25370 100755 --- a/WebServer/base/LogFile.h +++ b/WebServer/base/LogFile.h @@ -1,31 +1,31 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once +#include +#include #include "FileUtil.h" #include "MutexLock.h" #include "noncopyable.h" -#include -#include + // TODO 提供自动归档功能 -class LogFile : noncopyable -{ -public: - // 每被append flushEveryN次,flush一下,会往文件写,只不过,文件也是带缓冲区的 - LogFile(const std::string& basename, int flushEveryN = 1024); - ~LogFile(); +class LogFile : noncopyable { + public: + // 每被append flushEveryN次,flush一下,会往文件写,只不过,文件也是带缓冲区的 + LogFile(const std::string& basename, int flushEveryN = 1024); + ~LogFile(); - void append(const char* logline, int len); - void flush(); - bool rollFile(); + void append(const char* logline, int len); + void flush(); + bool rollFile(); -private: - void append_unlocked(const char* logline, int len); + private: + void append_unlocked(const char* logline, int len); - const std::string basename_; - const int flushEveryN_; + const std::string basename_; + const int flushEveryN_; - int count_; - std::unique_ptr mutex_; - std::unique_ptr file_; + int count_; + std::unique_ptr mutex_; + std::unique_ptr file_; }; \ No newline at end of file diff --git a/WebServer/base/LogStream.cpp b/WebServer/base/LogStream.cpp index bc6beaa..473e861 100755 --- a/WebServer/base/LogStream.cpp +++ b/WebServer/base/LogStream.cpp @@ -1,120 +1,101 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "LogStream.h" -#include -#include #include -#include #include #include - +#include +#include +#include const char digits[] = "9876543210123456789"; const char* zero = digits + 9; // From muduo -template -size_t convert(char buf[], T value) -{ - T i = value; - char *p = buf; - - do - { - int lsd = static_cast(i % 10); - i /= 10; - *p++ = zero[lsd]; - } while (i != 0); - - if (value < 0) - { - *p++ = '-'; - } - *p = '\0'; - std::reverse(buf, p); - - return p - buf; +template +size_t convert(char buf[], T value) { + T i = value; + char* p = buf; + + do { + int lsd = static_cast(i % 10); + i /= 10; + *p++ = zero[lsd]; + } while (i != 0); + + if (value < 0) { + *p++ = '-'; + } + *p = '\0'; + std::reverse(buf, p); + + return p - buf; } template class FixedBuffer; template class FixedBuffer; - -template -void LogStream::formatInteger(T v) -{ - // buffer容不下kMaxNumericSize个字符的话会被直接丢弃 - if (buffer_.avail() >= kMaxNumericSize) - { - size_t len = convert(buffer_.current(), v); - buffer_.add(len); - } +template +void LogStream::formatInteger(T v) { + // buffer容不下kMaxNumericSize个字符的话会被直接丢弃 + if (buffer_.avail() >= kMaxNumericSize) { + size_t len = convert(buffer_.current(), v); + buffer_.add(len); + } } -LogStream& LogStream::operator<<(short v) -{ - *this << static_cast(v); - return *this; +LogStream& LogStream::operator<<(short v) { + *this << static_cast(v); + return *this; } -LogStream& LogStream::operator<<(unsigned short v) -{ - *this << static_cast(v); - return *this; +LogStream& LogStream::operator<<(unsigned short v) { + *this << static_cast(v); + return *this; } -LogStream& LogStream::operator<<(int v) -{ - formatInteger(v); - return *this; +LogStream& LogStream::operator<<(int v) { + formatInteger(v); + return *this; } -LogStream& LogStream::operator<<(unsigned int v) -{ - formatInteger(v); - return *this; +LogStream& LogStream::operator<<(unsigned int v) { + formatInteger(v); + return *this; } -LogStream& LogStream::operator<<(long v) -{ - formatInteger(v); - return *this; +LogStream& LogStream::operator<<(long v) { + formatInteger(v); + return *this; } -LogStream& LogStream::operator<<(unsigned long v) -{ - formatInteger(v); - return *this; +LogStream& LogStream::operator<<(unsigned long v) { + formatInteger(v); + return *this; } -LogStream& LogStream::operator<<(long long v) -{ - formatInteger(v); - return *this; +LogStream& LogStream::operator<<(long long v) { + formatInteger(v); + return *this; } -LogStream& LogStream::operator<<(unsigned long long v) -{ - formatInteger(v); - return *this; +LogStream& LogStream::operator<<(unsigned long long v) { + formatInteger(v); + return *this; } -LogStream& LogStream::operator<<(double v) -{ - if (buffer_.avail() >= kMaxNumericSize) - { - int len = snprintf(buffer_.current(), kMaxNumericSize, "%.12g", v); - buffer_.add(len); - } - return *this; +LogStream& LogStream::operator<<(double v) { + if (buffer_.avail() >= kMaxNumericSize) { + int len = snprintf(buffer_.current(), kMaxNumericSize, "%.12g", v); + buffer_.add(len); + } + return *this; } -LogStream& LogStream::operator<<(long double v) -{ - if (buffer_.avail() >= kMaxNumericSize) - { - int len = snprintf(buffer_.current(), kMaxNumericSize, "%.12Lg", v); - buffer_.add(len); - } - return *this; +LogStream& LogStream::operator<<(long double v) { + if (buffer_.avail() >= kMaxNumericSize) { + int len = snprintf(buffer_.current(), kMaxNumericSize, "%.12Lg", v); + buffer_.add(len); + } + return *this; } \ No newline at end of file diff --git a/WebServer/base/LogStream.h b/WebServer/base/LogStream.h index 639596c..cb893cd 100755 --- a/WebServer/base/LogStream.h +++ b/WebServer/base/LogStream.h @@ -1,123 +1,106 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "noncopyable.h" #include #include #include - +#include "noncopyable.h" class AsyncLogging; const int kSmallBuffer = 4000; const int kLargeBuffer = 4000 * 1000; -template -class FixedBuffer: noncopyable -{ -public: - FixedBuffer() - : cur_(data_) - { } - - ~FixedBuffer() - { } - - void append(const char* buf, size_t len) - { - if (avail() > static_cast(len)) - { - memcpy(cur_, buf, len); - cur_ += len; - } - } - - const char* data() const { return data_; } - int length() const { return static_cast(cur_ - data_); } - - char* current() { return cur_; } - int avail() const { return static_cast(end() - cur_); } - void add(size_t len) { cur_ += len; } - - void reset() { cur_ = data_; } - void bzero() { memset(data_, 0, sizeof data_); } - - -private: - const char* end() const { return data_ + sizeof data_; } - - char data_[SIZE]; - char* cur_; -}; - +template +class FixedBuffer : noncopyable { + public: + FixedBuffer() : cur_(data_) {} + ~FixedBuffer() {} -class LogStream : noncopyable -{ -public: - typedef FixedBuffer Buffer; - - LogStream& operator<<(bool v) - { - buffer_.append(v ? "1" : "0", 1); - return *this; + void append(const char* buf, size_t len) { + if (avail() > static_cast(len)) { + memcpy(cur_, buf, len); + cur_ += len; } + } - LogStream& operator<<(short); - LogStream& operator<<(unsigned short); - LogStream& operator<<(int); - LogStream& operator<<(unsigned int); - LogStream& operator<<(long); - LogStream& operator<<(unsigned long); - LogStream& operator<<(long long); - LogStream& operator<<(unsigned long long); - - LogStream& operator<<(const void*); - - LogStream& operator<<(float v) - { - *this << static_cast(v); - return *this; - } - LogStream& operator<<(double); - LogStream& operator<<(long double); + const char* data() const { return data_; } + int length() const { return static_cast(cur_ - data_); } - LogStream& operator<<(char v) - { - buffer_.append(&v, 1); - return *this; - } + char* current() { return cur_; } + int avail() const { return static_cast(end() - cur_); } + void add(size_t len) { cur_ += len; } - LogStream& operator<<(const char* str) - { - if (str) - buffer_.append(str, strlen(str)); - else - buffer_.append("(null)", 6); - return *this; - } + void reset() { cur_ = data_; } + void bzero() { memset(data_, 0, sizeof data_); } - LogStream& operator<<(const unsigned char* str) - { - return operator<<(reinterpret_cast(str)); - } + private: + const char* end() const { return data_ + sizeof data_; } - LogStream& operator<<(const std::string& v) - { - buffer_.append(v.c_str(), v.size()); - return *this; - } - - void append(const char* data, int len) { buffer_.append(data, len); } - const Buffer& buffer() const { return buffer_; } - void resetBuffer() { buffer_.reset(); } - -private: - void staticCheck(); - - template - void formatInteger(T); - - Buffer buffer_; + char data_[SIZE]; + char* cur_; +}; - static const int kMaxNumericSize = 32; +class LogStream : noncopyable { + public: + typedef FixedBuffer Buffer; + + LogStream& operator<<(bool v) { + buffer_.append(v ? "1" : "0", 1); + return *this; + } + + LogStream& operator<<(short); + LogStream& operator<<(unsigned short); + LogStream& operator<<(int); + LogStream& operator<<(unsigned int); + LogStream& operator<<(long); + LogStream& operator<<(unsigned long); + LogStream& operator<<(long long); + LogStream& operator<<(unsigned long long); + + LogStream& operator<<(const void*); + + LogStream& operator<<(float v) { + *this << static_cast(v); + return *this; + } + LogStream& operator<<(double); + LogStream& operator<<(long double); + + LogStream& operator<<(char v) { + buffer_.append(&v, 1); + return *this; + } + + LogStream& operator<<(const char* str) { + if (str) + buffer_.append(str, strlen(str)); + else + buffer_.append("(null)", 6); + return *this; + } + + LogStream& operator<<(const unsigned char* str) { + return operator<<(reinterpret_cast(str)); + } + + LogStream& operator<<(const std::string& v) { + buffer_.append(v.c_str(), v.size()); + return *this; + } + + void append(const char* data, int len) { buffer_.append(data, len); } + const Buffer& buffer() const { return buffer_; } + void resetBuffer() { buffer_.reset(); } + + private: + void staticCheck(); + + template + void formatInteger(T); + + Buffer buffer_; + + static const int kMaxNumericSize = 32; }; \ No newline at end of file diff --git a/WebServer/base/Logging.cpp b/WebServer/base/Logging.cpp index 9663454..334cb4b 100755 --- a/WebServer/base/Logging.cpp +++ b/WebServer/base/Logging.cpp @@ -13,7 +13,7 @@ static pthread_once_t once_control_ = PTHREAD_ONCE_INIT; static AsyncLogging *AsyncLogger_; -std::string Logger::logFileName_ = "/linya_WebServer.log"; +std::string Logger::logFileName_ = "./WebServer.log"; void once_init() { diff --git a/WebServer/base/Logging.h b/WebServer/base/Logging.h index 6fa6d5e..a577be8 100755 --- a/WebServer/base/Logging.h +++ b/WebServer/base/Logging.h @@ -1,44 +1,36 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "LogStream.h" #include +#include #include #include -#include +#include "LogStream.h" -class AsyncLogging; +class AsyncLogging; -class Logger -{ -public: - Logger(const char *fileName, int line); - ~Logger(); - LogStream& stream() { return impl_.stream_; } +class Logger { + public: + Logger(const char *fileName, int line); + ~Logger(); + LogStream &stream() { return impl_.stream_; } - static void setLogFileName(std::string fileName) - { - logFileName_ = fileName; - } - static std::string getLogFileName() - { - return logFileName_; - } + static void setLogFileName(std::string fileName) { logFileName_ = fileName; } + static std::string getLogFileName() { return logFileName_; } -private: - class Impl - { - public: - Impl(const char *fileName, int line); - void formatTime(); + private: + class Impl { + public: + Impl(const char *fileName, int line); + void formatTime(); - LogStream stream_; - int line_; - std::string basename_; - }; - Impl impl_; - static std::string logFileName_; + LogStream stream_; + int line_; + std::string basename_; + }; + Impl impl_; + static std::string logFileName_; }; #define LOG Logger(__FILE__, __LINE__).stream() \ No newline at end of file diff --git a/WebServer/base/MutexLock.h b/WebServer/base/MutexLock.h index 88b36d2..5d2c42d 100755 --- a/WebServer/base/MutexLock.h +++ b/WebServer/base/MutexLock.h @@ -1,55 +1,35 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "noncopyable.h" #include #include +#include "noncopyable.h" + + +class MutexLock : noncopyable { + public: + MutexLock() { pthread_mutex_init(&mutex, NULL); } + ~MutexLock() { + pthread_mutex_lock(&mutex); + pthread_mutex_destroy(&mutex); + } + void lock() { pthread_mutex_lock(&mutex); } + void unlock() { pthread_mutex_unlock(&mutex); } + pthread_mutex_t *get() { return &mutex; } -class MutexLock: noncopyable -{ -public: - MutexLock() - { - pthread_mutex_init(&mutex, NULL); - } - ~MutexLock() - { - pthread_mutex_lock(&mutex); - pthread_mutex_destroy(&mutex); - } - void lock() - { - pthread_mutex_lock(&mutex); - } - void unlock() - { - pthread_mutex_unlock(&mutex); - } - pthread_mutex_t *get() - { - return &mutex; - } -private: - pthread_mutex_t mutex; + private: + pthread_mutex_t mutex; -// 友元类不受访问权限影响 -private: - friend class Condition; + // 友元类不受访问权限影响 + private: + friend class Condition; }; +class MutexLockGuard : noncopyable { + public: + explicit MutexLockGuard(MutexLock &_mutex) : mutex(_mutex) { mutex.lock(); } + ~MutexLockGuard() { mutex.unlock(); } -class MutexLockGuard: noncopyable -{ -public: - explicit MutexLockGuard(MutexLock &_mutex): - mutex(_mutex) - { - mutex.lock(); - } - ~MutexLockGuard() - { - mutex.unlock(); - } -private: - MutexLock &mutex; + private: + MutexLock &mutex; }; \ No newline at end of file diff --git a/WebServer/base/Thread.cpp b/WebServer/base/Thread.cpp index bb5cd6a..c021f85 100755 --- a/WebServer/base/Thread.cpp +++ b/WebServer/base/Thread.cpp @@ -1,133 +1,110 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #include "Thread.h" -#include "CurrentThread.h" -#include +#include #include +#include +#include #include -#include #include #include -#include -#include -#include +#include +#include +#include "CurrentThread.h" + #include using namespace std; - -namespace CurrentThread -{ - __thread int t_cachedTid = 0; - __thread char t_tidString[32]; - __thread int t_tidStringLength = 6; - __thread const char* t_threadName = "default"; +namespace CurrentThread { +__thread int t_cachedTid = 0; +__thread char t_tidString[32]; +__thread int t_tidStringLength = 6; +__thread const char* t_threadName = "default"; } +pid_t gettid() { return static_cast(::syscall(SYS_gettid)); } -pid_t gettid() -{ - return static_cast(::syscall(SYS_gettid)); -} - -void CurrentThread::cacheTid() -{ - if (t_cachedTid == 0) - { - t_cachedTid = gettid(); - t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid); - } +void CurrentThread::cacheTid() { + if (t_cachedTid == 0) { + t_cachedTid = gettid(); + t_tidStringLength = + snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid); + } } // 为了在线程中保留name,tid这些数据 -struct ThreadData -{ - typedef Thread::ThreadFunc ThreadFunc; - ThreadFunc func_; - string name_; - pid_t* tid_; - CountDownLatch* latch_; - - ThreadData(const ThreadFunc &func, const string& name, pid_t *tid, CountDownLatch *latch) - : func_(func), - name_(name), - tid_(tid), - latch_(latch) - { } - - void runInThread() - { - *tid_ = CurrentThread::tid(); - tid_ = NULL; - latch_->countDown(); - latch_ = NULL; - - CurrentThread::t_threadName = name_.empty() ? "Thread" : name_.c_str(); - prctl(PR_SET_NAME, CurrentThread::t_threadName); - - func_(); - CurrentThread::t_threadName = "finished"; - } +struct ThreadData { + typedef Thread::ThreadFunc ThreadFunc; + ThreadFunc func_; + string name_; + pid_t* tid_; + CountDownLatch* latch_; + + ThreadData(const ThreadFunc& func, const string& name, pid_t* tid, + CountDownLatch* latch) + : func_(func), name_(name), tid_(tid), latch_(latch) {} + + void runInThread() { + *tid_ = CurrentThread::tid(); + tid_ = NULL; + latch_->countDown(); + latch_ = NULL; + + CurrentThread::t_threadName = name_.empty() ? "Thread" : name_.c_str(); + prctl(PR_SET_NAME, CurrentThread::t_threadName); + + func_(); + CurrentThread::t_threadName = "finished"; + } }; -void *startThread(void* obj) -{ - ThreadData* data = static_cast(obj); - data->runInThread(); - delete data; - return NULL; +void* startThread(void* obj) { + ThreadData* data = static_cast(obj); + data->runInThread(); + delete data; + return NULL; } - -Thread::Thread(const ThreadFunc &func, const string &n) - : started_(false), - joined_(false), - pthreadId_(0), - tid_(0), - func_(func), - name_(n), - latch_(1) -{ - setDefaultName(); +Thread::Thread(const ThreadFunc& func, const string& n) + : started_(false), + joined_(false), + pthreadId_(0), + tid_(0), + func_(func), + name_(n), + latch_(1) { + setDefaultName(); } -Thread::~Thread() -{ - if (started_ && !joined_) - pthread_detach(pthreadId_); +Thread::~Thread() { + if (started_ && !joined_) pthread_detach(pthreadId_); } -void Thread::setDefaultName() -{ - if (name_.empty()) - { - char buf[32]; - snprintf(buf, sizeof buf, "Thread"); - name_ = buf; - } +void Thread::setDefaultName() { + if (name_.empty()) { + char buf[32]; + snprintf(buf, sizeof buf, "Thread"); + name_ = buf; + } } -void Thread::start() -{ - assert(!started_); - started_ = true; - ThreadData* data = new ThreadData(func_, name_, &tid_, &latch_); - if (pthread_create(&pthreadId_, NULL, &startThread, data)) - { - started_ = false; - delete data; - } - else - { - latch_.wait(); - assert(tid_ > 0); - } +void Thread::start() { + assert(!started_); + started_ = true; + ThreadData* data = new ThreadData(func_, name_, &tid_, &latch_); + if (pthread_create(&pthreadId_, NULL, &startThread, data)) { + started_ = false; + delete data; + } else { + latch_.wait(); + assert(tid_ > 0); + } } -int Thread::join() -{ - assert(started_); - assert(!joined_); - joined_ = true; - return pthread_join(pthreadId_, NULL); +int Thread::join() { + assert(started_); + assert(!joined_); + joined_ = true; + return pthread_join(pthreadId_, NULL); } \ No newline at end of file diff --git a/WebServer/base/Thread.h b/WebServer/base/Thread.h index 7dc1ed2..cb908dc 100755 --- a/WebServer/base/Thread.h +++ b/WebServer/base/Thread.h @@ -1,35 +1,33 @@ // @Author Lin Ya // @Email xxbbb@vip.qq.com #pragma once -#include "CountDownLatch.h" -#include "noncopyable.h" -#include -#include #include -#include #include #include +#include +#include +#include +#include "CountDownLatch.h" +#include "noncopyable.h" +class Thread : noncopyable { + public: + typedef std::function ThreadFunc; + explicit Thread(const ThreadFunc&, const std::string& name = std::string()); + ~Thread(); + void start(); + int join(); + bool started() const { return started_; } + pid_t tid() const { return tid_; } + const std::string& name() const { return name_; } -class Thread : noncopyable -{ -public: - typedef std::function ThreadFunc; - explicit Thread(const ThreadFunc&, const std::string& name = std::string()); - ~Thread(); - void start(); - int join(); - bool started() const { return started_; } - pid_t tid() const { return tid_; } - const std::string& name() const { return name_; } - -private: - void setDefaultName(); - bool started_; - bool joined_; - pthread_t pthreadId_; - pid_t tid_; - ThreadFunc func_; - std::string name_; - CountDownLatch latch_; + private: + void setDefaultName(); + bool started_; + bool joined_; + pthread_t pthreadId_; + pid_t tid_; + ThreadFunc func_; + std::string name_; + CountDownLatch latch_; }; \ No newline at end of file diff --git a/WebServer/base/noncopyable.h b/WebServer/base/noncopyable.h index 172b5f6..dd5ecef 100755 --- a/WebServer/base/noncopyable.h +++ b/WebServer/base/noncopyable.h @@ -2,12 +2,12 @@ // @Email xxbbb@vip.qq.com #pragma once -class noncopyable -{ -protected: - noncopyable() {} - ~noncopyable() {} -private: - noncopyable(const noncopyable&); - const noncopyable& operator=(const noncopyable&); +class noncopyable { + protected: + noncopyable() {} + ~noncopyable() {} + + private: + noncopyable(const noncopyable&); + const noncopyable& operator=(const noncopyable&); }; \ No newline at end of file diff --git a/WebServer/tests/HTTPClient.cpp b/WebServer/tests/HTTPClient.cpp index c71014e..96e0466 100755 --- a/WebServer/tests/HTTPClient.cpp +++ b/WebServer/tests/HTTPClient.cpp @@ -1,218 +1,209 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + using namespace std; - -#define MAXSIZE 1024 -#define IPADDRESS "127.0.0.1" -#define SERV_PORT 8888 -#define FDSIZE 1024 -#define EPOLLEVENTS 20 - -//static void handle_connection(int sockfd); -//static void handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf); -// static void do_read(int epollfd,int fd,int sockfd,char *buf); -// static void do_read(int epollfd,int fd,int sockfd,char *buf); -// static void do_write(int epollfd,int fd,int sockfd,char *buf); -// static void add_event(int epollfd,int fd,int state); -// static void delete_event(int epollfd,int fd,int state); -// static void modify_event(int epollfd,int fd,int state); - -int setSocketNonBlocking1(int fd) -{ - int flag = fcntl(fd, F_GETFL, 0); - if(flag == -1) - return -1; - flag |= O_NONBLOCK; - if(fcntl(fd, F_SETFL, flag) == -1) - return -1; - return 0; +#define MAXSIZE 1024 +#define IPADDRESS "127.0.0.1" +#define SERV_PORT 8888 +#define FDSIZE 1024 +#define EPOLLEVENTS 20 + +// static void handle_connection(int sockfd); +// static void handle_events(int epollfd,struct epoll_event *events,int num,int +// sockfd,char *buf); +// static void do_read(int epollfd,int fd,int sockfd,char *buf); +// static void do_read(int epollfd,int fd,int sockfd,char *buf); +// static void do_write(int epollfd,int fd,int sockfd,char *buf); +// static void add_event(int epollfd,int fd,int state); +// static void delete_event(int epollfd,int fd,int state); +// static void modify_event(int epollfd,int fd,int state); + +int setSocketNonBlocking1(int fd) { + int flag = fcntl(fd, F_GETFL, 0); + if (flag == -1) return -1; + + flag |= O_NONBLOCK; + if (fcntl(fd, F_SETFL, flag) == -1) return -1; + return 0; } -int main(int argc,char *argv[]) -{ - int sockfd; - struct sockaddr_in servaddr; - sockfd = socket(AF_INET,SOCK_STREAM,0); - bzero(&servaddr,sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(SERV_PORT); - inet_pton(AF_INET,IPADDRESS,&servaddr.sin_addr); - char buff[4096]; - buff[0] = '\0'; - // 发空串 - const char *p = " "; - if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == 0 ) - { - setSocketNonBlocking1(sockfd); - cout << "1:" << endl; - ssize_t n = write(sockfd, p, strlen(p)); - cout << "strlen(p) = " << strlen(p) << endl; - sleep(1); - n = read(sockfd, buff, 4096); - cout << "n=" << n << endl; - printf("%s", buff); - close(sockfd); - } - else{ - perror("err1"); - } +int main(int argc, char *argv[]) { + int sockfd; + struct sockaddr_in servaddr; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + bzero(&servaddr, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(SERV_PORT); + inet_pton(AF_INET, IPADDRESS, &servaddr.sin_addr); + char buff[4096]; + buff[0] = '\0'; + // 发空串 + const char *p = " "; + if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) { + setSocketNonBlocking1(sockfd); + cout << "1:" << endl; + ssize_t n = write(sockfd, p, strlen(p)); + cout << "strlen(p) = " << strlen(p) << endl; sleep(1); + n = read(sockfd, buff, 4096); + cout << "n=" << n << endl; + printf("%s", buff); + close(sockfd); + } else { + perror("err1"); + } + sleep(1); - // 发"GET HTTP/1.1" - p = "GET HTTP/1.1"; - sockfd = socket(AF_INET,SOCK_STREAM,0); - if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == 0) - { - setSocketNonBlocking1(sockfd); - cout << "2:" << endl; - ssize_t n = write(sockfd, p, strlen(p)); - cout << "strlen(p) = " << strlen(p) << endl; - sleep(1); - n = read(sockfd, buff, 4096); - cout << "n=" << n << endl; - printf("%s", buff); - close(sockfd); - } - else - { - perror("err2"); - } + // 发"GET HTTP/1.1" + p = "GET HTTP/1.1"; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) { + setSocketNonBlocking1(sockfd); + cout << "2:" << endl; + ssize_t n = write(sockfd, p, strlen(p)); + cout << "strlen(p) = " << strlen(p) << endl; sleep(1); + n = read(sockfd, buff, 4096); + cout << "n=" << n << endl; + printf("%s", buff); + close(sockfd); + } else { + perror("err2"); + } + sleep(1); + + // 发 + // GET HTTP/1.1 + // Host: 192.168.52.135:8888 + // Content-Type: application/x-www-form-urlencoded + // Connection: Keep-Alive + p = "GET / HTTP/1.1\r\nHost: 192.168.52.135:8888\r\nContent-Type: " + "application/x-www-form-urlencoded\r\nConnection: Keep-Alive\r\n\r\n"; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) { + setSocketNonBlocking1(sockfd); + cout << "3:" << endl; + ssize_t n = write(sockfd, p, strlen(p)); + cout << "strlen(p) = " << strlen(p) << endl; + sleep(1); + n = read(sockfd, buff, 4096); + cout << "n=" << n << endl; + printf("%s", buff); + close(sockfd); + } else { + perror("err3"); + } + return 0; +} + +// static void handle_connection(int sockfd) +// { +// int epollfd; +// struct epoll_event events[EPOLLEVENTS]; +// char buf[MAXSIZE]; +// int ret; +// epollfd = epoll_create(FDSIZE); +// add_event(epollfd,STDIN_FILENO,EPOLLIN); +// for ( ; ; ) +// { +// ret = epoll_wait(epollfd,events,EPOLLEVENTS,-1); +// handle_events(epollfd,events,ret,sockfd,buf); +// } +// close(epollfd); +// } - // 发 - // GET HTTP/1.1 - // Host: 192.168.52.135:8888 - // Content-Type: application/x-www-form-urlencoded - // Connection: Keep-Alive - p = "GET / HTTP/1.1\r\nHost: 192.168.52.135:8888\r\nContent-Type: application/x-www-form-urlencoded\r\nConnection: Keep-Alive\r\n\r\n"; - sockfd = socket(AF_INET,SOCK_STREAM,0); - if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == 0) - { - setSocketNonBlocking1(sockfd); - cout << "3:" << endl; - ssize_t n = write(sockfd, p, strlen(p)); - cout << "strlen(p) = " << strlen(p) << endl; - sleep(1); - n = read(sockfd, buff, 4096); - cout << "n=" << n << endl; - printf("%s", buff); - close(sockfd); - } - else - { - perror("err3"); - } - return 0; -} - - -// static void handle_connection(int sockfd) -// { -// int epollfd; -// struct epoll_event events[EPOLLEVENTS]; -// char buf[MAXSIZE]; -// int ret; -// epollfd = epoll_create(FDSIZE); -// add_event(epollfd,STDIN_FILENO,EPOLLIN); -// for ( ; ; ) -// { -// ret = epoll_wait(epollfd,events,EPOLLEVENTS,-1); -// handle_events(epollfd,events,ret,sockfd,buf); -// } -// close(epollfd); -// } - -// static void -// handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf) -// { -// int fd; -// int i; -// for (i = 0;i < num;i++) -// { -// fd = events[i].data.fd; -// if (events[i].events & EPOLLIN) -// do_read(epollfd,fd,sockfd,buf); -// else if (events[i].events & EPOLLOUT) -// do_write(epollfd,fd,sockfd,buf); -// } -// } - -// static void do_read(int epollfd,int fd,int sockfd,char *buf) -// { -// int nread; -// nread = read(fd,buf,MAXSIZE); -// if (nread == -1) -// { -// perror("read error:"); -// close(fd); -// } -// else if (nread == 0) -// { -// fprintf(stderr,"server close.\n"); -// close(fd); -// } -// else -// { -// if (fd == STDIN_FILENO) -// add_event(epollfd,sockfd,EPOLLOUT); -// else -// { -// delete_event(epollfd,sockfd,EPOLLIN); -// add_event(epollfd,STDOUT_FILENO,EPOLLOUT); -// } -// } -// } - -// static void do_write(int epollfd,int fd,int sockfd,char *buf) -// { -// int nwrite; -// nwrite = write(fd,buf,strlen(buf)); -// if (nwrite == -1) -// { -// perror("write error:"); -// close(fd); -// } +// static void +// handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char +// *buf) +// { +// int fd; +// int i; +// for (i = 0;i < num;i++) +// { +// fd = events[i].data.fd; +// if (events[i].events & EPOLLIN) +// do_read(epollfd,fd,sockfd,buf); +// else if (events[i].events & EPOLLOUT) +// do_write(epollfd,fd,sockfd,buf); +// } +// } + +// static void do_read(int epollfd,int fd,int sockfd,char *buf) +// { +// int nread; +// nread = read(fd,buf,MAXSIZE); +// if (nread == -1) +// { +// perror("read error:"); +// close(fd); +// } +// else if (nread == 0) +// { +// fprintf(stderr,"server close.\n"); +// close(fd); +// } +// else +// { +// if (fd == STDIN_FILENO) +// add_event(epollfd,sockfd,EPOLLOUT); +// else +// { +// delete_event(epollfd,sockfd,EPOLLIN); +// add_event(epollfd,STDOUT_FILENO,EPOLLOUT); +// } +// } +// } + +// static void do_write(int epollfd,int fd,int sockfd,char *buf) +// { +// int nwrite; +// nwrite = write(fd,buf,strlen(buf)); +// if (nwrite == -1) +// { +// perror("write error:"); +// close(fd); +// } // else -// { -// if (fd == STDOUT_FILENO) -// delete_event(epollfd,fd,EPOLLOUT); -// else -// modify_event(epollfd,fd,EPOLLIN); -// } -// memset(buf,0,MAXSIZE); -// } - -// static void add_event(int epollfd,int fd,int state) -// { -// struct epoll_event ev; -// ev.events = state; -// ev.data.fd = fd; -// epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev); +// { +// if (fd == STDOUT_FILENO) +// delete_event(epollfd,fd,EPOLLOUT); +// else +// modify_event(epollfd,fd,EPOLLIN); +// } +// memset(buf,0,MAXSIZE); // } - -// static void delete_event(int epollfd,int fd,int state) -// { -// struct epoll_event ev; -// ev.events = state; -// ev.data.fd = fd; -// epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev); -// } - -// static void modify_event(int epollfd,int fd,int state) -// { -// struct epoll_event ev; -// ev.events = state; -// ev.data.fd = fd; -// epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev); -// } \ No newline at end of file + +// static void add_event(int epollfd,int fd,int state) +// { +// struct epoll_event ev; +// ev.events = state; +// ev.data.fd = fd; +// epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev); +// } + +// static void delete_event(int epollfd,int fd,int state) +// { +// struct epoll_event ev; +// ev.events = state; +// ev.data.fd = fd; +// epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev); +// } + +// static void modify_event(int epollfd,int fd,int state) +// { +// struct epoll_event ev; +// ev.events = state; +// ev.data.fd = fd; +// epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev); +// } \ No newline at end of file diff --git a/build.sh b/build.sh index 50b9889..a979aa5 100755 --- a/build.sh +++ b/build.sh @@ -4,7 +4,7 @@ set -x SOURCE_DIR=`pwd` BUILD_DIR=${BUILD_DIR:-../build} -BUILD_TYPE=${BUILD_TYPE:-release} +BUILD_TYPE=${BUILD_TYPE:-Debug} mkdir -p $BUILD_DIR/$BUILD_TYPE \ && cd $BUILD_DIR/$BUILD_TYPE \