├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── WebServer ├── CMakeLists.txt ├── Channel.cpp ├── Channel.h ├── Epoll.cpp ├── Epoll.h ├── EventLoop.cpp ├── EventLoop.h ├── EventLoopThread.cpp ├── EventLoopThread.h ├── EventLoopThreadPool.cpp ├── EventLoopThreadPool.h ├── HttpData.cpp ├── HttpData.h ├── Main.cpp ├── Makefile ├── Makefile.bak ├── Server.cpp ├── Server.h ├── ThreadPool.cpp ├── ThreadPool.h ├── Timer.cpp ├── Timer.h ├── Util.cpp ├── Util.h ├── base │ ├── AsyncLogging.cpp │ ├── AsyncLogging.h │ ├── CMakeLists.txt │ ├── Condition.h │ ├── CountDownLatch.cpp │ ├── CountDownLatch.h │ ├── CurrentThread.h │ ├── FileUtil.cpp │ ├── FileUtil.h │ ├── LogFile.cpp │ ├── LogFile.h │ ├── LogStream.cpp │ ├── LogStream.h │ ├── Logging.cpp │ ├── Logging.h │ ├── Log的设计.txt │ ├── MutexLock.h │ ├── Thread.cpp │ ├── Thread.h │ ├── noncopyable.h │ └── tests │ │ ├── CMakeLists.txt │ │ └── LoggingTest.cpp ├── config.h └── tests │ ├── CMakeLists.txt │ ├── HTTPClient.cpp │ └── build │ └── release │ ├── CMakeCache.txt │ └── CMakeFiles │ ├── 2.8.12.2 │ ├── CMakeCCompiler.cmake │ ├── CMakeCXXCompiler.cmake │ ├── CMakeDetermineCompilerABI_C.bin │ ├── CMakeDetermineCompilerABI_CXX.bin │ ├── CMakeSystem.cmake │ ├── CompilerIdC │ │ └── CMakeCCompilerId.c │ └── CompilerIdCXX │ │ └── CMakeCXXCompilerId.cpp │ ├── CMakeError.log │ ├── CMakeOutput.log │ └── cmake.check_cache └── build.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | 34 | # Otheres 35 | core 36 | .vscode 37 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | sudo: required 3 | dist: trusty 4 | compiler: 5 | - g++ 6 | os: 7 | - linux 8 | install: 9 | - sudo apt-get install cmake 10 | env: 11 | - BUILD_TYPE=debug 12 | - BUILD_TYPE=release 13 | script: 14 | - ./build.sh 15 | 16 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | project(WebServer CXX) 4 | 5 | if(NOT CMAKE_BUILD_TYPE) 6 | set(CMAKE_BUILD_TYPE "Release") 7 | endif() 8 | 9 | set(CXX_FLAGS 10 | -g 11 | -Wall 12 | -std=c++11 13 | -D_PTHREADS 14 | -Wno-unused-parameter 15 | ) 16 | 17 | 18 | set(CMAKE_CXX_COMPILER "g++") 19 | set(CMAKE_CXX_FLAGS_DEBUG "-O0") 20 | set(CMAKE_CXX_FLAGS_RELEASE "-O3") 21 | 22 | string(REPLACE ";" " " CMAKE_CXX_FLAGS "${CXX_FLAGS}") 23 | 24 | 25 | string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE) 26 | message(STATUS "CXX_FLAGS = " ${CMAKE_CXX_FLAGS} " " ${CMAKE_CXX_FLAGS_${BUILD_TYPE}}) 27 | 28 | add_subdirectory(WebServer) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A C++ High Performance Web Server 2 | 3 | 4 | ## Introduction 5 | 参考linyacool的[Web Server](https://github.com/linyacool/WebServer )和 chenshuo的[muduo](https://github.com/chenshuo/muduo)。 6 | 7 | 前期主要是学习阅读源码,对比muduo的功能和实现,基本上将所有的类都注释过了。 8 | 9 | 后期待改进计划: 10 | 11 | 1. 当前定时器不能精确的处理定时任务,后面改用timefd来实现定时器; 12 | 2. 当前服务器的各个配置参数分散在源文件中,后面改用JSON格式的配置文件集中配置参数; 13 | 3. 将socket fd和其操作封装为RAII类; 14 | 4. 目前用std::string做读写缓冲,性能有限,后面参考muduo实现自己的读写缓冲; 15 | 5. 目前的Server类比较混乱,后面进行整理拆分,拆成TcpServer,TcpConnect和Accpetor,支持主动关闭和被动关闭; 16 | 6. 支持更多的HTTP请求方法和返回状态码(当前只支持400,404); 17 | 7. 支持HTTPS。 18 | 19 | 本项目为C++11编写的Web服务器,解析了get请求,可处理静态资源,支持HTTP长连接。 20 | 21 | ## Envoirment 22 | * OS: Ubuntu 14.04 23 | * Complier: g++ 4.8 24 | 25 | ## Build 26 | 27 | ./build.sh 28 | 29 | ## Usage 30 | 31 | ./WebServer [-t thread_numbers] [-p port] [-l log_file_path(should begin with '/')] 32 | 33 | ## Technical points 34 | * 使用Epoll边沿触发的IO多路复用技术,非阻塞IO,使用Reactor模式 35 | * 使用多线程充分利用多核CPU,并使用线程池避免线程频繁创建销毁的开销 36 | * 使用基于小根堆的定时器关闭超时请求 37 | * 主线程只负责accept请求,并以Round Robin的方式分发给其它IO线程(兼计算线程),锁的争用只会出现在主线程和某一特定线程中 38 | * 使用eventfd实现了线程的异步唤醒 39 | * 为减少内存泄漏的可能,使用智能指针等RAII机制 40 | * 使用状态机解析了HTTP请求 41 | 42 | 43 | -------------------------------------------------------------------------------- /WebServer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(SRCS 2 | Channel.cpp 3 | Epoll.cpp 4 | EventLoop.cpp 5 | EventLoopThread.cpp 6 | EventLoopThreadPool.cpp 7 | HttpData.cpp 8 | Main.cpp 9 | Server.cpp 10 | #ThreadPool.cpp 11 | Timer.cpp 12 | Util.cpp 13 | ) 14 | include_directories(${PROJECT_SOURCE_DIR}/base) 15 | 16 | 17 | add_executable(WebServer ${SRCS}) 18 | target_link_libraries(WebServer libserver_base) 19 | 20 | 21 | add_subdirectory(base) 22 | add_subdirectory(tests) -------------------------------------------------------------------------------- /WebServer/Channel.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Channel.h" 4 | #include "Util.h" 5 | #include "Epoll.h" 6 | #include "EventLoop.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | using namespace std; 12 | 13 | Channel::Channel(EventLoop *loop): 14 | loop_(loop), 15 | events_(0), 16 | lastEvents_(0) 17 | { } 18 | 19 | Channel::Channel(EventLoop *loop, int fd): 20 | loop_(loop), 21 | fd_(fd), 22 | events_(0), 23 | lastEvents_(0) 24 | { } 25 | 26 | Channel::~Channel() 27 | { 28 | //loop_->poller_->epoll_del(fd, events_); 29 | //close(fd_); // 为什么不关闭描述符 ??? 30 | } 31 | 32 | int Channel::getFd() 33 | { 34 | return fd_; 35 | } 36 | void Channel::setFd(int fd) 37 | { 38 | fd_ = fd; 39 | } 40 | 41 | void Channel::handleRead() 42 | { 43 | if (readHandler_) 44 | { 45 | readHandler_(); 46 | } 47 | } 48 | 49 | void Channel::handleWrite() 50 | { 51 | if (writeHandler_) 52 | { 53 | writeHandler_(); 54 | } 55 | } 56 | 57 | void Channel::handleConn() 58 | { 59 | if (connHandler_) 60 | { 61 | connHandler_(); 62 | } 63 | } -------------------------------------------------------------------------------- /WebServer/Channel.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "Timer.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | class EventLoop; 14 | class HttpData; 15 | 16 | /* 17 | Channel是selectable IO channel,负责注册和响应IO事件 18 | 每个Channel对象自始至终只属于一个EventLoop, 因此每个Channel对象都只属于一个IO线程 19 | 每个Channel对象自始至终只负责一个文件描述符(fd)的IO事件分发,但它不拥有这个fd,也不会在析构时关闭fd 20 | Channel会把不同的IO事件分发为不同的回调,例如ReadCallback、WriteCallback、errorCallback 21 | 22 | 这里的Channel把muduo中的Acceptor(接收器,用于服务端接受连接)也揉进了这个类中,增加了connCallback 23 | 把TcpConnection(TCP连接器,用于处理连接)也揉进了这个类中,增加了holder, 24 | 25 | handleEvent()是Channel的核心,它由EventLoop::loop()调用,它的功能是根据revents_的值分别调用不同的用户回调 26 | 27 | 28 | Channel类的作用是把fd 和fd感兴趣的IO事件,和fd上就绪的IO事件,以及对相应的IO事件进行处理的函数封装到一起 29 | */ 30 | 31 | class Channel 32 | { 33 | private: 34 | typedef std::function CallBack; 35 | EventLoop *loop_; // 自始至终属于一个EventLoop管理 36 | int fd_; // Channel管理的fd 37 | __uint32_t events_; // epoll或poll的结构体(epoll_event或pollfd)中events变量, 保存了fd上感兴趣的IO事件 38 | __uint32_t revents_; // 目前fd上就绪的事件,是由Epoll类的poll方法获得 39 | __uint32_t lastEvents_; 40 | 41 | // 方便找到上层持有该Channel的对象 42 | std::weak_ptr holder_; 43 | 44 | private: 45 | int parse_URI(); 46 | int parse_Headers(); 47 | int analysisRequest(); 48 | 49 | CallBack readHandler_; 50 | CallBack writeHandler_; 51 | CallBack errorHandler_; 52 | CallBack connHandler_; 53 | 54 | public: 55 | Channel(EventLoop *loop); 56 | Channel(EventLoop *loop, int fd); 57 | ~Channel(); 58 | int getFd(); // 返回管理的fd 59 | void setFd(int fd); // 设置管理的fd 60 | 61 | // 62 | void setHolder(std::shared_ptr holder) 63 | { 64 | holder_ = holder; 65 | } 66 | std::shared_ptr getHolder() 67 | { 68 | std::shared_ptr ret(holder_.lock()); 69 | return ret; 70 | } 71 | 72 | void setReadHandler(CallBack &&readHandler) 73 | { 74 | readHandler_ = readHandler; 75 | } 76 | void setWriteHandler(CallBack &&writeHandler) 77 | { 78 | writeHandler_ = writeHandler; 79 | } 80 | void setErrorHandler(CallBack &&errorHandler) 81 | { 82 | errorHandler_ = errorHandler; 83 | } 84 | void setConnHandler(CallBack &&connHandler) 85 | { 86 | connHandler_ = connHandler; 87 | } 88 | 89 | // handleEvent()是Channel的核心,它由EventLoop::loop()调用,它的功能是根据revents_的值分别调用不同的用户回调 90 | void handleEvents() 91 | { 92 | events_ = 0; 93 | if ((revents_ & EPOLLHUP) && !(revents_ & EPOLLIN)) // 挂起(管道的写端被关闭,读端将收到EPOLLHUP事件) 并且 无数据可读 94 | { 95 | events_ = 0; 96 | return; 97 | } 98 | if (revents_ & EPOLLERR) // 错误 99 | { 100 | if (errorHandler_) errorHandler_(); 101 | events_ = 0; 102 | return; 103 | } 104 | if (revents_ & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) // 数据可读 或 高优先级数据可读(TCP带外数据) 或 对方关闭了写操作 105 | { 106 | handleRead(); 107 | } 108 | if (revents_ & EPOLLOUT) // 数据可写 109 | { 110 | handleWrite(); 111 | } 112 | handleConn(); // 处理连接 113 | } 114 | void handleRead(); 115 | void handleWrite(); 116 | void handleError(int fd, int err_num, std::string short_msg); 117 | void handleConn(); 118 | 119 | void setRevents(__uint32_t ev) // 设置fd上的就绪事件 120 | { 121 | revents_ = ev; 122 | } 123 | 124 | void setEvents(__uint32_t ev) // 设置fd上的感兴趣事件 125 | { 126 | events_ = ev; 127 | } 128 | __uint32_t& getEvents() // 返回感兴趣事件 129 | { 130 | return events_; 131 | } 132 | 133 | bool EqualAndUpdateLastEvents() // 更新上次注册的事件 134 | { 135 | bool ret = (lastEvents_ == events_); 136 | lastEvents_ = events_; 137 | return ret; 138 | } 139 | 140 | __uint32_t getLastEvents() 141 | { 142 | return lastEvents_; 143 | } 144 | 145 | }; 146 | 147 | typedef std::shared_ptr SP_Channel; -------------------------------------------------------------------------------- /WebServer/Epoll.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Epoll.h" 4 | #include "Util.h" 5 | #include "base/Logging.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | using namespace std; 18 | 19 | 20 | const int EVENTSNUM = 4096; // 同时就绪fd数目的上限 21 | const int EPOLLWAIT_TIME = 10000; //超时时间 22 | 23 | typedef shared_ptr SP_Channel; 24 | 25 | Epoll::Epoll(): 26 | epollFd_(epoll_create1(EPOLL_CLOEXEC)), //调用epoll_create1创建内核事件表 27 | events_(EVENTSNUM) // 结构体数组大小 28 | { 29 | assert(epollFd_ > 0); 30 | } 31 | Epoll::~Epoll() 32 | { } 33 | 34 | 35 | // 注册新描述符 36 | // 在往内核表中注册fd时,添加了定时器 37 | // 封装epoll_ctl( ,EPOLL_CTL_ADD, , )函数,将Channel中的感兴趣的事件注册到内核表中 38 | void Epoll::epoll_add(SP_Channel request, int timeout) 39 | { 40 | int fd = request->getFd(); 41 | 42 | 43 | if (timeout > 0) 44 | { 45 | add_timer(request, timeout); 46 | fd2http_[fd] = request->getHolder(); 47 | } 48 | struct epoll_event event; 49 | event.data.fd = fd; 50 | event.events = request->getEvents(); 51 | 52 | request->EqualAndUpdateLastEvents(); 53 | 54 | fd2chan_[fd] = request; 55 | if(epoll_ctl(epollFd_, EPOLL_CTL_ADD, fd, &event) < 0) 56 | { 57 | perror("epoll_add error"); 58 | fd2chan_[fd].reset(); 59 | } 60 | } 61 | 62 | 63 | // 修改描述符状态 64 | // 封装epoll_ctl( ,EPOLL_CTL_MOD, , )函数,修改内核表中之前注册的fd感兴趣的事件 65 | // 66 | void Epoll::epoll_mod(SP_Channel request, int timeout) 67 | { 68 | // 69 | if (timeout > 0) 70 | add_timer(request, timeout); 71 | int fd = request->getFd(); 72 | if (!request->EqualAndUpdateLastEvents()) // 判断是否有修改,不相等则有修改 73 | { 74 | struct epoll_event event; 75 | event.data.fd = fd; 76 | event.events = request->getEvents(); 77 | if(epoll_ctl(epollFd_, EPOLL_CTL_MOD, fd, &event) < 0) 78 | { 79 | perror("epoll_mod error"); 80 | fd2chan_[fd].reset(); 81 | } 82 | } 83 | } 84 | 85 | 86 | // 从epoll中删除描述符 87 | // 封装epoll_ctl( ,EPOLL_CTL_DEL, , )函数,删除内核表中之前注册的fd 88 | void Epoll::epoll_del(SP_Channel request) 89 | { 90 | int fd = request->getFd(); 91 | struct epoll_event event; 92 | event.data.fd = fd; 93 | event.events = request->getLastEvents(); 94 | //event.events = 0; 95 | // request->EqualAndUpdateLastEvents() 96 | if(epoll_ctl(epollFd_, EPOLL_CTL_DEL, fd, &event) < 0) 97 | { 98 | perror("epoll_del error"); 99 | } 100 | fd2chan_[fd].reset(); // 减少引用计数,指针置空 101 | fd2http_[fd].reset(); // 减少引用计数,指针置空 102 | } 103 | 104 | 105 | 106 | /* Epoll类的核心功能函数poll */ 107 | // 返回活跃事件数 108 | // 调用epoll_wait函数,返回一个已就绪的Channel数组 109 | std::vector Epoll::poll() 110 | { 111 | while (true) 112 | { 113 | int event_count = epoll_wait(epollFd_, &*events_.begin(), events_.size(), EPOLLWAIT_TIME); 114 | if (event_count < 0) 115 | perror("epoll wait error"); 116 | std::vector req_data = getEventsRequest(event_count); // 处理epoll_wait的返回结果,将就绪的事件,保存在channel数组中。 117 | if (req_data.size() > 0) 118 | return req_data; 119 | } 120 | } 121 | 122 | // 处理超时事件 123 | void Epoll::handleExpired() 124 | { 125 | timerManager_.handleExpiredEvent(); 126 | } 127 | 128 | // 129 | // 获取就绪的fd及其上的就绪事件 130 | std::vector Epoll::getEventsRequest(int events_num) 131 | { 132 | std::vector req_data; // 要返回的就绪Channel指针数组 133 | // 遍历events_结构体数组 134 | for(int i = 0; i < events_num; ++i) 135 | { 136 | // 获取有事件产生的描述符 137 | int fd = events_[i].data.fd; 138 | 139 | // 与该fd对应的Channel对象的指针 140 | SP_Channel cur_req = fd2chan_[fd]; 141 | 142 | if (cur_req) 143 | { 144 | cur_req->setRevents(events_[i].events); // 获取fd上的就绪事件,设置管理该fd的Channel对象上的就绪事件 145 | cur_req->setEvents(0); // 清空感兴趣的事件 146 | // 加入线程池之前将Timer和request分离 147 | //cur_req->seperateTimer(); 148 | req_data.push_back(cur_req); // 将此Channel指针加入到要返回的就绪数组中 149 | } 150 | else 151 | { 152 | LOG << "SP cur_req is invalid"; 153 | } 154 | } 155 | return req_data; 156 | } 157 | 158 | // 添加定时器 159 | void Epoll::add_timer(SP_Channel request_data, int timeout) 160 | { 161 | // 找到持有Channel对象的HttpData 162 | shared_ptr t = request_data->getHolder(); 163 | // 调用 164 | if (t) 165 | timerManager_.addTimer(t, timeout); 166 | else 167 | LOG << "timer add fail"; 168 | } -------------------------------------------------------------------------------- /WebServer/Epoll.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "Channel.h" 5 | #include "HttpData.h" 6 | #include "Timer.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | 只负责IO复用 14 | poll函数是Epoll的核心功能,获取当前活动的IO事件,返回就绪的Channel对象 15 | 16 | Epoll内部维护一个内核事件表,所有fd和Channel的对应关系,事件管理类TimerManager对象,并封装了函数epoll_ctl()和epoll_wait() 17 | 18 | */ 19 | class Epoll 20 | { 21 | public: 22 | Epoll(); 23 | ~Epoll(); 24 | void epoll_add(SP_Channel request, int timeout); 25 | void epoll_mod(SP_Channel request, int timeout); 26 | void epoll_del(SP_Channel request); 27 | std::vector> poll(); // 核心功能 28 | std::vector> getEventsRequest(int events_num); 29 | int getEpollFd() 30 | { 31 | return epollFd_; 32 | } 33 | /* 后面这两个函数用来处理定时器 本不应该放在这个类中 */ 34 | 35 | // 增加定时器 36 | void add_timer(std::shared_ptr request_data, int timeout); 37 | 38 | // 处理超时 39 | void handleExpired(); 40 | 41 | private: 42 | static const int MAXFDS = 100000; // IO复用管理的fd数目的上限 43 | int epollFd_; // epfd内核事件表描述符 44 | std::vector events_; // epoll_event结构体数组,从内核事件表将所有就绪的事件复制到此 45 | std::shared_ptr fd2chan_[MAXFDS]; // fd To(对应) Channel的数组,相当于一个固定大小的map 46 | std::shared_ptr fd2http_[MAXFDS]; // fd To(对应)Http的数组,相当于一个固定大小的map 47 | TimerManager timerManager_; // 定时器管理类 本不应该在这里 48 | }; -------------------------------------------------------------------------------- /WebServer/EventLoop.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "EventLoop.h" 4 | #include "base/Logging.h" 5 | #include "Util.h" 6 | #include 7 | #include 8 | #include 9 | using namespace std; 10 | 11 | __thread EventLoop* t_loopInThisThread = 0; 12 | 13 | // 创建eventfd并返回 14 | int createEventfd() 15 | { 16 | int evtfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 17 | if (evtfd < 0) 18 | { 19 | LOG << "Failed in eventfd"; 20 | abort(); 21 | } 22 | return evtfd; 23 | } 24 | 25 | EventLoop::EventLoop() 26 | : looping_(false), 27 | poller_(new Epoll()), 28 | wakeupFd_(createEventfd()), 29 | quit_(false), 30 | eventHandling_(false), 31 | callingPendingFunctors_(false), 32 | threadId_(CurrentThread::tid()), 33 | pwakeupChannel_(new Channel(this, wakeupFd_)) // 用pwakeupChannel_来管理wakeupFd_ 34 | { 35 | if (t_loopInThisThread) 36 | { 37 | //LOG << "Another EventLoop " << t_loopInThisThread << " exists in this thread " << threadId_; 38 | } 39 | else 40 | { 41 | t_loopInThisThread = this; 42 | } 43 | //pwakeupChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); 44 | // 设置pwakeupChannel_的IO回调事件 45 | pwakeupChannel_->setEvents(EPOLLIN | EPOLLET); 46 | pwakeupChannel_->setReadHandler(bind(&EventLoop::handleRead, this)); 47 | pwakeupChannel_->setConnHandler(bind(&EventLoop::handleConn, this)); 48 | poller_->epoll_add(pwakeupChannel_, 0); 49 | } 50 | 51 | void EventLoop::handleConn() 52 | { 53 | //poller_->epoll_mod(wakeupFd_, pwakeupChannel_, (EPOLLIN | EPOLLET | EPOLLONESHOT), 0); 54 | updatePoller(pwakeupChannel_, 0); 55 | } 56 | 57 | 58 | EventLoop::~EventLoop() 59 | { 60 | //wakeupChannel_->disableAll(); 61 | //wakeupChannel_->remove(); 62 | close(wakeupFd_); 63 | t_loopInThisThread = NULL; 64 | } 65 | 66 | // 向wakeupFd_写入1,原本阻塞在epoll_wait()的线程会返回 67 | void EventLoop::wakeup() 68 | { 69 | uint64_t one = 1; 70 | ssize_t n = writen(wakeupFd_, (char*)(&one), sizeof one); 71 | if (n != sizeof one) 72 | { 73 | LOG<< "EventLoop::wakeup() writes " << n << " bytes instead of 8"; 74 | } 75 | } 76 | 77 | // 处理wakeupFd_上的读事件 78 | void EventLoop::handleRead() 79 | { 80 | uint64_t one = 1; 81 | ssize_t n = readn(wakeupFd_, &one, sizeof one); 82 | if (n != sizeof one) 83 | { 84 | LOG << "EventLoop::handleRead() reads " << n << " bytes instead of 8"; 85 | } 86 | //pwakeupChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); 87 | pwakeupChannel_->setEvents(EPOLLIN | EPOLLET); 88 | } 89 | 90 | // 在IO线程内执行某个用户任务回调 91 | void EventLoop::runInLoop(Functor&& cb) 92 | { 93 | if (isInLoopThread()) //如果用户在当前IO线程调用,回调会进行 94 | cb(); 95 | else 96 | queueInLoop(std::move(cb));// 在其他线程中调用,cb会被加入队列中,IO线程会被唤醒,来调用这个cb 97 | } 98 | 99 | // 将cb放入队列中,并在必要时唤醒IO线程,多线程操作需要加锁 100 | void EventLoop::queueInLoop(Functor&& cb) 101 | { 102 | { 103 | MutexLockGuard lock(mutex_); 104 | pendingFunctors_.emplace_back(std::move(cb)); 105 | } 106 | 107 | // 如果调用queueInLoop()的函数的线程不是IO线程 或者 正在执行pending functor 唤醒线程 108 | if (!isInLoopThread() || callingPendingFunctors_) 109 | wakeup(); 110 | } 111 | 112 | /* EventLoop类的核心功能函数loop() */ 113 | // 在无限循环中 114 | // 1. 通过调用方法Epoll:poll(),获取当前就绪的Channel指针数组 115 | // 2. 对每个就绪的fd,调用handleEvents()处理其上就绪的事件 116 | // 3. 处理queueInLoop上的回调 117 | // 4. 处理超时事件 118 | void EventLoop::loop() 119 | { 120 | assert(!looping_); 121 | assert(isInLoopThread()); // 保证每个线程只能有一个EventLoop 122 | looping_ = true; 123 | quit_ = false; 124 | //LOG_TRACE << "EventLoop " << this << " start looping"; 125 | //typedef std::shared_ptr SP_Channel; 126 | std::vector ret; // IO复用类Epoll:poll(),返回的当前就绪的Channel指针数组 127 | while (!quit_) 128 | { 129 | //cout << "doing" << endl; 130 | ret.clear(); 131 | /* 关键步骤1:获取IO复用的结果,当前就绪的Channel指针数组 */ 132 | ret = poller_->poll(); 133 | 134 | /* 关键步骤2:*/ 135 | eventHandling_ = true; 136 | for (auto &it : ret) 137 | it->handleEvents(); 138 | eventHandling_ = false; 139 | 140 | /* 关键步骤3:*/ 141 | doPendingFunctors(); 142 | 143 | /* 关键步骤4:*/ 144 | poller_->handleExpired(); 145 | } 146 | looping_ = false; 147 | } 148 | 149 | // 执行回调列表中的回调函数 150 | void EventLoop::doPendingFunctors() 151 | { 152 | std::vector functors; 153 | callingPendingFunctors_ = true; 154 | 155 | // 临界区,把回调列表swap()到局部变量中,减小了临界区的长度,也避免了死锁 156 | { 157 | MutexLockGuard lock(mutex_); 158 | functors.swap(pendingFunctors_); 159 | } 160 | 161 | // 依次调用Functor 162 | for (size_t i = 0; i < functors.size(); ++i) 163 | functors[i](); 164 | callingPendingFunctors_ = false; 165 | } 166 | 167 | // 退出loop循环 168 | void EventLoop::quit() 169 | { 170 | quit_ = true; 171 | if (!isInLoopThread()) 172 | { 173 | wakeup(); 174 | } 175 | } -------------------------------------------------------------------------------- /WebServer/EventLoop.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "base/Thread.h" 5 | #include "Epoll.h" 6 | #include "base/Logging.h" 7 | #include "Channel.h" 8 | #include "base/CurrentThread.h" 9 | #include "Util.h" 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | using namespace std; 16 | 17 | /* 18 | 事件循环类 19 | EventLoop拥有并管理一个Epoll类对象,并管理归属于本EventLoop对象的Channel对象 20 | (每个Channel对象自始至终只属于一个EventLoop) 21 | 创建了EventLoop对象的线程是IO线程,其主要功能是运行事件循环loop(), 22 | 不断的获取就绪事件Epoll:poll(),并处理事件Channel::handleEvent() 23 | 24 | EventLoop实现了一个功能:在IO线程中执行某个用户回调,即runInLoop()函数; 25 | IO线程平时阻塞在loop()的epoll_wait()调用中,为了立刻执行用户回调,需要唤醒线程, 26 | 这里利用eventfd来唤醒线程 27 | 28 | */ 29 | class EventLoop 30 | { 31 | public: 32 | typedef std::function Functor; 33 | EventLoop(); 34 | ~EventLoop(); 35 | void loop(); // 循环函数 36 | void quit(); // 退出函数 37 | void runInLoop(Functor&& cb); // 在IO线程内执行某个用户任务回调 38 | void queueInLoop(Functor&& cb); // cb会被加入队列中,IO线程会被唤醒来调用这个cb 39 | bool isInLoopThread() const { return threadId_ == CurrentThread::tid(); } // 判断是否是当前线程,每个线程只能有一个EventLoop对象 40 | void assertInLoopThread() // 检查当前线程是否已经创建了其他EventLoop对象 41 | { 42 | assert(isInLoopThread()); 43 | } 44 | 45 | // 关闭一个fd的读写 46 | void shutdown(shared_ptr channel) 47 | { 48 | shutDownWR(channel->getFd()); 49 | } 50 | 51 | // 从IO复用类对象中poller_中移除Channel对象 52 | void removeFromPoller(shared_ptr channel) 53 | { 54 | //shutDownWR(channel->getFd()); 55 | poller_->epoll_del(channel); 56 | } 57 | 58 | // 向IO复用类对象中poller_中更新Channel对象 59 | void updatePoller(shared_ptr channel, int timeout = 0) 60 | { 61 | poller_->epoll_mod(channel, timeout); 62 | } 63 | 64 | // 向IO复用类对象中poller_中添加Channel对象 65 | void addToPoller(shared_ptr channel, int timeout = 0) 66 | { 67 | poller_->epoll_add(channel, timeout); 68 | } 69 | 70 | private: 71 | // 声明顺序 wakeupFd_ > pwakeupChannel_ 72 | bool looping_; 73 | shared_ptr poller_; // 每个事件循环中都有一个IO复用 74 | int wakeupFd_; // eventfd 75 | bool quit_; 76 | bool eventHandling_; 77 | mutable MutexLock mutex_; 78 | std::vector pendingFunctors_; // 保存回调函数,暴露给了其他线程,需要用mutex保护 79 | bool callingPendingFunctors_; // 是否正在调用pending functor 80 | const pid_t threadId_; // 线程id,EventLoop的构造函数会记住本对象所属的线程 81 | shared_ptr pwakeupChannel_; // 把wakeupFd_包装进Channel对象来管理 82 | 83 | void wakeup(); 84 | void handleRead(); 85 | void doPendingFunctors(); 86 | void handleConn(); 87 | }; 88 | -------------------------------------------------------------------------------- /WebServer/EventLoopThread.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "EventLoopThread.h" 4 | #include 5 | 6 | 7 | EventLoopThread::EventLoopThread() 8 | : loop_(NULL), 9 | exiting_(false), 10 | thread_(bind(&EventLoopThread::threadFunc, this), "EventLoopThread"), // 初始化线程对象 11 | mutex_(), 12 | cond_(mutex_) // 初始化条件变量 13 | { } 14 | 15 | EventLoopThread::~EventLoopThread() 16 | { 17 | exiting_ = true; 18 | if (loop_ != NULL) 19 | { 20 | loop_->quit(); 21 | thread_.join(); 22 | } 23 | } 24 | 25 | // 开启线程,内部通过条件变量,保证线程内事件循环类的loop开启 26 | // 因为是通过一个EventLoopThread对象创建所有子线程,所以要用条件变量 + 互斥锁 27 | EventLoop* EventLoopThread::startLoop() 28 | { 29 | assert(!thread_.started()); 30 | // 创建线程 31 | thread_.start(); 32 | 33 | // 条件变量使用原则 34 | // 1. 加锁(在已上锁的情况下才可以调用wait()) 35 | // 2. 把判断条件和wait()放到while循环中 36 | { 37 | MutexLockGuard lock(mutex_); 38 | // 一直等到threadFun在Thread里真正跑起来 39 | while (loop_ == NULL) 40 | cond_.wait(); 41 | } 42 | return loop_; 43 | } 44 | 45 | // EventLoopThread运行的线程函数 46 | // 栈上变量EventLoop对象 47 | void EventLoopThread::threadFunc() 48 | { 49 | EventLoop loop; 50 | 51 | { 52 | MutexLockGuard lock(mutex_); // 加锁 53 | loop_ = &loop; 54 | cond_.notify(); // 条件变量通知 55 | } 56 | 57 | loop.loop(); // 调用loop()开启事件循环 58 | //assert(exiting_); 59 | loop_ = NULL; 60 | } -------------------------------------------------------------------------------- /WebServer/EventLoopThread.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "base/Condition.h" 5 | #include "base/MutexLock.h" 6 | #include "base/Thread.h" 7 | #include "base/noncopyable.h" 8 | #include "EventLoop.h" 9 | 10 | /* 11 | EventLoopThread类 12 | one loop per thread原则 13 | EventLoopThread类会启动自己的线程startLoop(),并在其中运行EventLoop::loop() 14 | */ 15 | 16 | class EventLoopThread :noncopyable 17 | { 18 | public: 19 | EventLoopThread(); 20 | ~EventLoopThread(); 21 | EventLoop* startLoop(); 22 | 23 | private: 24 | void threadFunc(); 25 | EventLoop *loop_; 26 | bool exiting_; 27 | Thread thread_; 28 | MutexLock mutex_; 29 | Condition cond_; 30 | }; -------------------------------------------------------------------------------- /WebServer/EventLoopThreadPool.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "EventLoopThreadPool.h" 4 | 5 | // 构造函数,baseLoop以调用构造函数者所拥有的EventLoop传入 6 | EventLoopThreadPool::EventLoopThreadPool(EventLoop* baseLoop, int numThreads) 7 | : baseLoop_(baseLoop), 8 | started_(false), 9 | numThreads_(numThreads), 10 | next_(0) 11 | { 12 | if (numThreads_ <= 0) 13 | { 14 | LOG << "numThreads_ <= 0"; 15 | abort(); 16 | } 17 | } 18 | // 19 | void EventLoopThreadPool::start() 20 | { 21 | baseLoop_->assertInLoopThread(); 22 | started_ = true; 23 | for (int i = 0; i < numThreads_; ++i) 24 | { 25 | // 创建指定数目的线程 26 | std::shared_ptr t(new EventLoopThread()); 27 | threads_.push_back(t); 28 | loops_.push_back(t->startLoop()); // 开启子线程的loop() 29 | } 30 | } 31 | 32 | // round-robin轮询调度 33 | EventLoop *EventLoopThreadPool::getNextLoop() 34 | { 35 | baseLoop_->assertInLoopThread(); 36 | assert(started_); 37 | EventLoop *loop = baseLoop_; 38 | // 如果子线程为空,就返回主线程loop 39 | if (!loops_.empty()) 40 | { 41 | loop = loops_[next_]; 42 | next_ = (next_ + 1) % numThreads_; // 不为空则轮询 43 | } 44 | return loop; 45 | } -------------------------------------------------------------------------------- /WebServer/EventLoopThreadPool.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "base/noncopyable.h" 5 | #include "EventLoopThread.h" 6 | #include "base/Logging.h" 7 | #include 8 | #include 9 | /* 10 | 线程池类 11 | one loop per thread思想 12 | 就是TcpServer自己的Eventloop(baseLoop)只用来接受新连接 13 | 新连接会从event loop pool 中选择一个EventLoop来用 14 | */ 15 | 16 | class EventLoopThreadPool : noncopyable 17 | { 18 | public: 19 | EventLoopThreadPool(EventLoop* baseLoop, int numThreads); 20 | 21 | ~EventLoopThreadPool() 22 | { 23 | LOG << "~EventLoopThreadPool()"; 24 | } 25 | void start(); 26 | 27 | EventLoop *getNextLoop(); 28 | 29 | private: 30 | /* 31 | 线程池拥有一个EventLoop对象 32 | 和线程对象vector 33 | 和EventLoop对象vector 34 | */ 35 | EventLoop* baseLoop_; 36 | bool started_; 37 | int numThreads_; 38 | int next_; // 下一个要 39 | std::vector> threads_; // 池中所有线程对象的指针 40 | std::vector loops_; // 池中所有线程对象中 41 | }; -------------------------------------------------------------------------------- /WebServer/HttpData.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "HttpData.h" 4 | #include "time.h" 5 | #include "Channel.h" 6 | #include "Util.h" 7 | #include "EventLoop.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | using namespace std; 13 | 14 | pthread_once_t MimeType::once_control = PTHREAD_ONCE_INIT; 15 | std::unordered_map MimeType::mime; 16 | 17 | 18 | const __uint32_t DEFAULT_EVENT = EPOLLIN | EPOLLET | EPOLLONESHOT; 19 | const int DEFAULT_EXPIRED_TIME = 2000; // ms 20 | const int DEFAULT_KEEP_ALIVE_TIME = 5 * 60 * 1000; // ms 21 | 22 | char favicon[555] = { 23 | '\x89', 'P', 'N', 'G', '\xD', '\xA', '\x1A', '\xA', 24 | '\x0', '\x0', '\x0', '\xD', 'I', 'H', 'D', 'R', 25 | '\x0', '\x0', '\x0', '\x10', '\x0', '\x0', '\x0', '\x10', 26 | '\x8', '\x6', '\x0', '\x0', '\x0', '\x1F', '\xF3', '\xFF', 27 | 'a', '\x0', '\x0', '\x0', '\x19', 't', 'E', 'X', 28 | 't', 'S', 'o', 'f', 't', 'w', 'a', 'r', 29 | 'e', '\x0', 'A', 'd', 'o', 'b', 'e', '\x20', 30 | 'I', 'm', 'a', 'g', 'e', 'R', 'e', 'a', 31 | 'd', 'y', 'q', '\xC9', 'e', '\x3C', '\x0', '\x0', 32 | '\x1', '\xCD', 'I', 'D', 'A', 'T', 'x', '\xDA', 33 | '\x94', '\x93', '9', 'H', '\x3', 'A', '\x14', '\x86', 34 | '\xFF', '\x5D', 'b', '\xA7', '\x4', 'R', '\xC4', 'm', 35 | '\x22', '\x1E', '\xA0', 'F', '\x24', '\x8', '\x16', '\x16', 36 | 'v', '\xA', '6', '\xBA', 'J', '\x9A', '\x80', '\x8', 37 | 'A', '\xB4', 'q', '\x85', 'X', '\x89', 'G', '\xB0', 38 | 'I', '\xA9', 'Q', '\x24', '\xCD', '\xA6', '\x8', '\xA4', 39 | 'H', 'c', '\x91', 'B', '\xB', '\xAF', 'V', '\xC1', 40 | 'F', '\xB4', '\x15', '\xCF', '\x22', 'X', '\x98', '\xB', 41 | 'T', 'H', '\x8A', 'd', '\x93', '\x8D', '\xFB', 'F', 42 | 'g', '\xC9', '\x1A', '\x14', '\x7D', '\xF0', 'f', 'v', 43 | 'f', '\xDF', '\x7C', '\xEF', '\xE7', 'g', 'F', '\xA8', 44 | '\xD5', 'j', 'H', '\x24', '\x12', '\x2A', '\x0', '\x5', 45 | '\xBF', 'G', '\xD4', '\xEF', '\xF7', '\x2F', '6', '\xEC', 46 | '\x12', '\x20', '\x1E', '\x8F', '\xD7', '\xAA', '\xD5', '\xEA', 47 | '\xAF', 'I', '5', 'F', '\xAA', 'T', '\x5F', '\x9F', 48 | '\x22', 'A', '\x2A', '\x95', '\xA', '\x83', '\xE5', 'r', 49 | '9', 'd', '\xB3', 'Y', '\x96', '\x99', 'L', '\x6', 50 | '\xE9', 't', '\x9A', '\x25', '\x85', '\x2C', '\xCB', 'T', 51 | '\xA7', '\xC4', 'b', '1', '\xB5', '\x5E', '\x0', '\x3', 52 | 'h', '\x9A', '\xC6', '\x16', '\x82', '\x20', 'X', 'R', 53 | '\x14', 'E', '6', 'S', '\x94', '\xCB', 'e', 'x', 54 | '\xBD', '\x5E', '\xAA', 'U', 'T', '\x23', 'L', '\xC0', 55 | '\xE0', '\xE2', '\xC1', '\x8F', '\x0', '\x9E', '\xBC', '\x9', 56 | 'A', '\x7C', '\x3E', '\x1F', '\x83', 'D', '\x22', '\x11', 57 | '\xD5', 'T', '\x40', '\x3F', '8', '\x80', 'w', '\xE5', 58 | '3', '\x7', '\xB8', '\x5C', '\x2E', 'H', '\x92', '\x4', 59 | '\x87', '\xC3', '\x81', '\x40', '\x20', '\x40', 'g', '\x98', 60 | '\xE9', '6', '\x1A', '\xA6', 'g', '\x15', '\x4', '\xE3', 61 | '\xD7', '\xC8', '\xBD', '\x15', '\xE1', 'i', '\xB7', 'C', 62 | '\xAB', '\xEA', 'x', '\x2F', 'j', 'X', '\x92', '\xBB', 63 | '\x18', '\x20', '\x9F', '\xCF', '3', '\xC3', '\xB8', '\xE9', 64 | 'N', '\xA7', '\xD3', 'l', 'J', '\x0', 'i', '6', 65 | '\x7C', '\x8E', '\xE1', '\xFE', 'V', '\x84', '\xE7', '\x3C', 66 | '\x9F', 'r', '\x2B', '\x3A', 'B', '\x7B', '7', 'f', 67 | 'w', '\xAE', '\x8E', '\xE', '\xF3', '\xBD', 'R', '\xA9', 68 | 'd', '\x2', 'B', '\xAF', '\x85', '2', 'f', 'F', 69 | '\xBA', '\xC', '\xD9', '\x9F', '\x1D', '\x9A', 'l', '\x22', 70 | '\xE6', '\xC7', '\x3A', '\x2C', '\x80', '\xEF', '\xC1', '\x15', 71 | '\x90', '\x7', '\x93', '\xA2', '\x28', '\xA0', 'S', 'j', 72 | '\xB1', '\xB8', '\xDF', '\x29', '5', 'C', '\xE', '\x3F', 73 | 'X', '\xFC', '\x98', '\xDA', 'y', 'j', 'P', '\x40', 74 | '\x0', '\x87', '\xAE', '\x1B', '\x17', 'B', '\xB4', '\x3A', 75 | '\x3F', '\xBE', 'y', '\xC7', '\xA', '\x26', '\xB6', '\xEE', 76 | '\xD9', '\x9A', '\x60', '\x14', '\x93', '\xDB', '\x8F', '\xD', 77 | '\xA', '\x2E', '\xE9', '\x23', '\x95', '\x29', 'X', '\x0', 78 | '\x27', '\xEB', 'n', 'V', 'p', '\xBC', '\xD6', '\xCB', 79 | '\xD6', 'G', '\xAB', '\x3D', 'l', '\x7D', '\xB8', '\xD2', 80 | '\xDD', '\xA0', '\x60', '\x83', '\xBA', '\xEF', '\x5F', '\xA4', 81 | '\xEA', '\xCC', '\x2', 'N', '\xAE', '\x5E', 'p', '\x1A', 82 | '\xEC', '\xB3', '\x40', '9', '\xAC', '\xFE', '\xF2', '\x91', 83 | '\x89', 'g', '\x91', '\x85', '\x21', '\xA8', '\x87', '\xB7', 84 | 'X', '\x7E', '\x7E', '\x85', '\xBB', '\xCD', 'N', 'N', 85 | 'b', 't', '\x40', '\xFA', '\x93', '\x89', '\xEC', '\x1E', 86 | '\xEC', '\x86', '\x2', 'H', '\x26', '\x93', '\xD0', 'u', 87 | '\x1D', '\x7F', '\x9', '2', '\x95', '\xBF', '\x1F', '\xDB', 88 | '\xD7', 'c', '\x8A', '\x1A', '\xF7', '\x5C', '\xC1', '\xFF', 89 | '\x22', 'J', '\xC3', '\x87', '\x0', '\x3', '\x0', 'K', 90 | '\xBB', '\xF8', '\xD6', '\x2A', 'v', '\x98', 'I', '\x0', 91 | '\x0', '\x0', '\x0', 'I', 'E', 'N', 'D', '\xAE', 92 | 'B', '\x60', '\x82', 93 | }; 94 | 95 | void MimeType::init() 96 | { 97 | mime[".html"] = "text/html"; 98 | mime[".avi"] = "video/x-msvideo"; 99 | mime[".bmp"] = "image/bmp"; 100 | mime[".c"] = "text/plain"; 101 | mime[".doc"] = "application/msword"; 102 | mime[".gif"] = "image/gif"; 103 | mime[".gz"] = "application/x-gzip"; 104 | mime[".htm"] = "text/html"; 105 | mime[".ico"] = "image/x-icon"; 106 | mime[".jpg"] = "image/jpeg"; 107 | mime[".png"] = "image/png"; 108 | mime[".txt"] = "text/plain"; 109 | mime[".mp3"] = "audio/mp3"; 110 | mime["default"] = "text/html"; 111 | } 112 | 113 | std::string MimeType::getMime(const std::string &suffix) 114 | { 115 | pthread_once(&once_control, MimeType::init); 116 | if (mime.find(suffix) == mime.end()) 117 | return mime["default"]; 118 | else 119 | return mime[suffix]; 120 | } 121 | 122 | 123 | HttpData::HttpData(EventLoop *loop, int connfd): 124 | loop_(loop), 125 | channel_(new Channel(loop, connfd)), // new一个新的Channel对象,包装连接描述符 126 | fd_(connfd), 127 | error_(false), 128 | connectionState_(H_CONNECTED), 129 | method_(METHOD_GET), 130 | HTTPVersion_(HTTP_11), 131 | nowReadPos_(0), 132 | state_(STATE_PARSE_URI), 133 | hState_(H_START), 134 | keepAlive_(false) 135 | { 136 | //loop_->queueInLoop(bind(&HttpData::setHandlers, this)); 137 | channel_->setReadHandler(bind(&HttpData::handleRead, this)); // 已连接描述符的读事件 138 | channel_->setWriteHandler(bind(&HttpData::handleWrite, this)); // 已连接描述符的写事件 139 | channel_->setConnHandler(bind(&HttpData::handleConn, this)); // 已连接描述符的连接事件 140 | } 141 | 142 | // 重置 143 | void HttpData::reset() 144 | { 145 | //inBuffer_.clear(); 146 | fileName_.clear(); 147 | path_.clear(); 148 | nowReadPos_ = 0; 149 | state_ = STATE_PARSE_URI; 150 | hState_ = H_START; 151 | headers_.clear(); 152 | //keepAlive_ = false; 153 | if (timer_.lock()) 154 | { 155 | shared_ptr my_timer(timer_.lock()); 156 | my_timer->clearReq(); 157 | timer_.reset(); 158 | } 159 | } 160 | 161 | // 分离定时器,把原本绑定在HttpData上的旧的定时器分离,并将其设置为删除的 162 | void HttpData::seperateTimer() 163 | { 164 | //cout << "seperateTimer" << endl; 165 | if (timer_.lock()) 166 | { 167 | shared_ptr my_timer(timer_.lock()); 168 | my_timer->clearReq(); 169 | timer_.reset(); 170 | } 171 | } 172 | 173 | 174 | // 核心函数1:读取解析http请求 175 | void HttpData::handleRead() 176 | { 177 | __uint32_t &events_ = channel_->getEvents(); 178 | do 179 | { 180 | bool zero = false; 181 | int read_num = readn(fd_, inBuffer_, zero); 182 | LOG << "Request: " << inBuffer_; 183 | 184 | // 正在断开连接,清空读入缓冲,退出循环 185 | if (connectionState_ == H_DISCONNECTING) 186 | { 187 | inBuffer_.clear(); 188 | break; 189 | } 190 | //cout << inBuffer_ << endl; 191 | 192 | // 如果没有读入数据就处理错误400 193 | if (read_num < 0) 194 | { 195 | perror("1"); 196 | error_ = true; 197 | handleError(fd_, 400, "Bad Request"); 198 | break; 199 | } 200 | // else if (read_num == 0) 201 | // { 202 | // error_ = true; 203 | // break; 204 | // } 205 | 206 | // read返回零,客户端已经断开了连接 207 | else if (zero) 208 | { 209 | // 有请求出现但是读不到数据,可能是Request Aborted,或者来自网络的数据没有达到等原因 210 | // 最可能是对端已经关闭了,统一按照对端已经关闭处理 211 | //error_ = true; 212 | connectionState_ = H_DISCONNECTING; 213 | if (read_num == 0) 214 | { 215 | //error_ = true; 216 | break; 217 | } 218 | //cout << "readnum == 0" << endl; 219 | } 220 | 221 | // 解析请求行 222 | if (state_ == STATE_PARSE_URI) 223 | { 224 | URIState flag = this->parseURI(); 225 | if (flag == PARSE_URI_AGAIN) 226 | break; 227 | else if (flag == PARSE_URI_ERROR) 228 | { 229 | perror("2"); 230 | LOG << "FD = " << fd_ << "," << inBuffer_ << "******"; 231 | inBuffer_.clear(); 232 | error_ = true; 233 | handleError(fd_, 400, "Bad Request"); 234 | break; 235 | } 236 | else 237 | state_ = STATE_PARSE_HEADERS; 238 | } 239 | 240 | // 解析头部字段,保存结构在headers_的map中 241 | if (state_ == STATE_PARSE_HEADERS) 242 | { 243 | HeaderState flag = this->parseHeaders(); 244 | if (flag == PARSE_HEADER_AGAIN) 245 | break; 246 | else if (flag == PARSE_HEADER_ERROR) 247 | { 248 | perror("3"); 249 | error_ = true; 250 | handleError(fd_, 400, "Bad Request"); 251 | break; 252 | } 253 | if(method_ == METHOD_POST) 254 | { 255 | // POST方法准备 256 | state_ = STATE_RECV_BODY; 257 | } 258 | else 259 | { 260 | state_ = STATE_ANALYSIS; 261 | } 262 | } 263 | 264 | // 解析消息体 265 | if (state_ == STATE_RECV_BODY) 266 | { 267 | int content_length = -1; 268 | if (headers_.find("Content-length") != headers_.end()) 269 | { 270 | content_length = stoi(headers_["Content-length"]); 271 | } 272 | else 273 | { 274 | //cout << "(state_ == STATE_RECV_BODY)" << endl; 275 | error_ = true; 276 | handleError(fd_, 400, "Bad Request: Lack of argument (Content-length)"); 277 | break; 278 | } 279 | if (static_cast(inBuffer_.size()) < content_length) 280 | break; 281 | state_ = STATE_ANALYSIS; 282 | } 283 | if (state_ == STATE_ANALYSIS) 284 | { 285 | AnalysisState flag = this->analysisRequest(); 286 | if (flag == ANALYSIS_SUCCESS) 287 | { 288 | state_ = STATE_FINISH; 289 | break; 290 | } 291 | else 292 | { 293 | //cout << "state_ == STATE_ANALYSIS" << endl; 294 | error_ = true; 295 | break; 296 | } 297 | } 298 | } while (false); 299 | //cout << "state_=" << state_ << endl; 300 | if (!error_) 301 | { 302 | if (outBuffer_.size() > 0) 303 | { 304 | handleWrite(); 305 | //events_ |= EPOLLOUT; 306 | } 307 | // error_ may change 308 | if (!error_ && state_ == STATE_FINISH) 309 | { 310 | this->reset(); 311 | if (inBuffer_.size() > 0) 312 | { 313 | if (connectionState_ != H_DISCONNECTING) 314 | handleRead(); 315 | } 316 | 317 | // if ((keepAlive_ || inBuffer_.size() > 0) && connectionState_ == H_CONNECTED) 318 | // { 319 | // this->reset(); 320 | // events_ |= EPOLLIN; 321 | // } 322 | } 323 | else if (!error_ && connectionState_ != H_DISCONNECTED) 324 | events_ |= EPOLLIN; 325 | } 326 | } 327 | 328 | 329 | 330 | // 核心函数2:写入http响应,将输出缓冲写入socket fd 331 | void HttpData::handleWrite() 332 | { 333 | if (!error_ && connectionState_ != H_DISCONNECTED) 334 | { 335 | __uint32_t &events_ = channel_->getEvents(); 336 | if (writen(fd_, outBuffer_) < 0) 337 | { 338 | perror("writen"); 339 | events_ = 0; 340 | error_ = true; 341 | } 342 | if (outBuffer_.size() > 0) 343 | events_ |= EPOLLOUT; 344 | } 345 | } 346 | 347 | 348 | 349 | 350 | void HttpData::handleConn() 351 | { 352 | // 分离定时器,该socket上发生了事件,就要更新定时器时间,做法是:把旧的定时器丢弃,重新绑定新的定时器 353 | seperateTimer(); 354 | __uint32_t &events_ = channel_->getEvents(); 355 | 356 | // 设置感兴趣的events事件 357 | if (!error_ && connectionState_ == H_CONNECTED) // 旧的已经建立连接的fd 358 | { 359 | if (events_ != 0) 360 | { 361 | int timeout = DEFAULT_EXPIRED_TIME; 362 | if (keepAlive_) 363 | timeout = DEFAULT_KEEP_ALIVE_TIME; 364 | if ((events_ & EPOLLIN) && (events_ & EPOLLOUT)) // 非新建的连接,就监听可写事件 365 | { 366 | events_ = __uint32_t(0); 367 | events_ |= EPOLLOUT; 368 | } 369 | //events_ |= (EPOLLET | EPOLLONESHOT); 370 | events_ |= EPOLLET; 371 | loop_->updatePoller(channel_, timeout); 372 | 373 | } 374 | else if (keepAlive_) // 新到来的连接,就监听可读事件 375 | { 376 | events_ |= (EPOLLIN | EPOLLET); 377 | //events_ |= (EPOLLIN | EPOLLET | EPOLLONESHOT); 378 | int timeout = DEFAULT_KEEP_ALIVE_TIME; 379 | loop_->updatePoller(channel_, timeout); 380 | } 381 | else // 新到来的连接,且不是 382 | { 383 | //cout << "close normally" << endl; 384 | // loop_->shutdown(channel_); 385 | // loop_->runInLoop(bind(&HttpData::handleClose, shared_from_this())); 386 | events_ |= (EPOLLIN | EPOLLET); 387 | //events_ |= (EPOLLIN | EPOLLET | EPOLLONESHOT); 388 | int timeout = (DEFAULT_KEEP_ALIVE_TIME >> 1); // 为什么不用DEFAULT_EXPIRED_TIME 389 | loop_->updatePoller(channel_, timeout); 390 | } 391 | } 392 | else if (!error_ && connectionState_ == H_DISCONNECTING && (events_ & EPOLLOUT)) 393 | { 394 | events_ = (EPOLLOUT | EPOLLET); 395 | } 396 | else 397 | { 398 | //cout << "close with errors" << endl; 399 | loop_->runInLoop(bind(&HttpData::handleClose, shared_from_this())); 400 | } 401 | } 402 | 403 | 404 | // 解析请求头 405 | URIState HttpData::parseURI() 406 | { 407 | string &str = inBuffer_; 408 | string cop = str; 409 | // 读到完整的请求行再开始解析请求 410 | size_t pos = str.find('\r', nowReadPos_); 411 | if (pos < 0) 412 | { 413 | return PARSE_URI_AGAIN; 414 | } 415 | // 去掉请求行所占的空间,节省空间 416 | string request_line = str.substr(0, pos); 417 | if (str.size() > pos + 1) 418 | str = str.substr(pos + 1); 419 | else 420 | str.clear(); 421 | 422 | // 解析请求方法 423 | // Method 424 | int posGet = request_line.find("GET"); 425 | int posPost = request_line.find("POST"); 426 | int posHead = request_line.find("HEAD"); 427 | 428 | if (posGet >= 0) 429 | { 430 | pos = posGet; 431 | method_ = METHOD_GET; 432 | } 433 | else if (posPost >= 0) 434 | { 435 | pos = posPost; 436 | method_ = METHOD_POST; 437 | } 438 | else if (posHead >= 0) 439 | { 440 | pos = posHead; 441 | method_ = METHOD_HEAD; 442 | } 443 | else 444 | { 445 | return PARSE_URI_ERROR; 446 | } 447 | 448 | // 解析URI 449 | // 获取文件名 450 | // filename 451 | pos = request_line.find("/", pos); 452 | if (pos < 0) 453 | { 454 | fileName_ = "index.html"; 455 | HTTPVersion_ = HTTP_11; 456 | return PARSE_URI_SUCCESS; 457 | } 458 | else 459 | { 460 | size_t _pos = request_line.find(' ', pos); 461 | if (_pos < 0) 462 | return PARSE_URI_ERROR; 463 | else 464 | { 465 | if (_pos - pos > 1) 466 | { 467 | fileName_ = request_line.substr(pos + 1, _pos - pos - 1); 468 | size_t __pos = fileName_.find('?'); 469 | if (__pos >= 0) 470 | { 471 | fileName_ = fileName_.substr(0, __pos); 472 | } 473 | } 474 | 475 | else 476 | fileName_ = "index.html"; 477 | } 478 | pos = _pos; 479 | } 480 | //cout << "fileName_: " << fileName_ << endl; 481 | // 解析HTTP 版本号 482 | pos = request_line.find("/", pos); 483 | if (pos < 0) 484 | return PARSE_URI_ERROR; 485 | else 486 | { 487 | if (request_line.size() - pos <= 3) 488 | return PARSE_URI_ERROR; 489 | else 490 | { 491 | string ver = request_line.substr(pos + 1, 3); 492 | if (ver == "1.0") 493 | HTTPVersion_ = HTTP_10; 494 | else if (ver == "1.1") 495 | HTTPVersion_ = HTTP_11; 496 | else 497 | return PARSE_URI_ERROR; 498 | } 499 | } 500 | return PARSE_URI_SUCCESS; 501 | } 502 | 503 | // 解析请求头部字段,保存结构在headers_的map中 504 | HeaderState HttpData::parseHeaders() 505 | { 506 | string &str = inBuffer_; 507 | int key_start = -1, key_end = -1, value_start = -1, value_end = -1; 508 | int now_read_line_begin = 0; 509 | bool notFinish = true; 510 | size_t i = 0; 511 | for (; i < str.size() && notFinish; ++i) 512 | { 513 | switch(hState_) 514 | { 515 | case H_START: 516 | { 517 | if (str[i] == '\n' || str[i] == '\r') 518 | break; 519 | hState_ = H_KEY; 520 | key_start = i; 521 | now_read_line_begin = i; 522 | break; 523 | } 524 | case H_KEY: 525 | { 526 | if (str[i] == ':') 527 | { 528 | key_end = i; 529 | if (key_end - key_start <= 0) 530 | return PARSE_HEADER_ERROR; 531 | hState_ = H_COLON; 532 | } 533 | else if (str[i] == '\n' || str[i] == '\r') 534 | return PARSE_HEADER_ERROR; 535 | break; 536 | } 537 | case H_COLON: 538 | { 539 | if (str[i] == ' ') 540 | { 541 | hState_ = H_SPACES_AFTER_COLON; 542 | } 543 | else 544 | return PARSE_HEADER_ERROR; 545 | break; 546 | } 547 | case H_SPACES_AFTER_COLON: 548 | { 549 | hState_ = H_VALUE; 550 | value_start = i; 551 | break; 552 | } 553 | case H_VALUE: 554 | { 555 | if (str[i] == '\r') 556 | { 557 | hState_ = H_CR; 558 | value_end = i; 559 | if (value_end - value_start <= 0) 560 | return PARSE_HEADER_ERROR; 561 | } 562 | else if (i - value_start > 255) 563 | return PARSE_HEADER_ERROR; 564 | break; 565 | } 566 | case H_CR: 567 | { 568 | if (str[i] == '\n') 569 | { 570 | hState_ = H_LF; 571 | string key(str.begin() + key_start, str.begin() + key_end); 572 | string value(str.begin() + value_start, str.begin() + value_end); 573 | headers_[key] = value; 574 | now_read_line_begin = i; 575 | } 576 | else 577 | return PARSE_HEADER_ERROR; 578 | break; 579 | } 580 | case H_LF: 581 | { 582 | if (str[i] == '\r') 583 | { 584 | hState_ = H_END_CR; 585 | } 586 | else 587 | { 588 | key_start = i; 589 | hState_ = H_KEY; 590 | } 591 | break; 592 | } 593 | case H_END_CR: 594 | { 595 | if (str[i] == '\n') 596 | { 597 | hState_ = H_END_LF; 598 | } 599 | else 600 | return PARSE_HEADER_ERROR; 601 | break; 602 | } 603 | case H_END_LF: 604 | { 605 | notFinish = false; 606 | key_start = i; 607 | now_read_line_begin = i; 608 | break; 609 | } 610 | } 611 | } 612 | if (hState_ == H_END_LF) 613 | { 614 | str = str.substr(i); 615 | return PARSE_HEADER_SUCCESS; 616 | } 617 | str = str.substr(now_read_line_begin); 618 | return PARSE_HEADER_AGAIN; 619 | } 620 | 621 | // 分析http请求,生成要写入的响应数据 622 | AnalysisState HttpData::analysisRequest() 623 | { 624 | if (method_ == METHOD_POST) 625 | { 626 | // ------------------------------------------------------ 627 | // My CV stitching handler which requires OpenCV library 628 | // ------------------------------------------------------ 629 | // string header; 630 | // header += string("HTTP/1.1 200 OK\r\n"); 631 | // if(headers_.find("Connection") != headers_.end() && headers_["Connection"] == "Keep-Alive") 632 | // { 633 | // keepAlive_ = true; 634 | // header += string("Connection: Keep-Alive\r\n") + "Keep-Alive: timeout=" + to_string(DEFAULT_KEEP_ALIVE_TIME) + "\r\n"; 635 | // } 636 | // int length = stoi(headers_["Content-length"]); 637 | // vector data(inBuffer_.begin(), inBuffer_.begin() + length); 638 | // Mat src = imdecode(data, CV_LOAD_IMAGE_ANYDEPTH|CV_LOAD_IMAGE_ANYCOLOR); 639 | // //imwrite("receive.bmp", src); 640 | // Mat res = stitch(src); 641 | // vector data_encode; 642 | // imencode(".png", res, data_encode); 643 | // header += string("Content-length: ") + to_string(data_encode.size()) + "\r\n\r\n"; 644 | // outBuffer_ += header + string(data_encode.begin(), data_encode.end()); 645 | // inBuffer_ = inBuffer_.substr(length); 646 | // return ANALYSIS_SUCCESS; 647 | } 648 | else if (method_ == METHOD_GET || method_ == METHOD_HEAD) 649 | { 650 | string header; 651 | // 状态行 652 | header += "HTTP/1.1 200 OK\r\n"; 653 | 654 | // 处理响应头部字段 655 | if(headers_.find("Connection") != headers_.end() && (headers_["Connection"] == "Keep-Alive" || headers_["Connection"] == "keep-alive")) 656 | { 657 | keepAlive_ = true; 658 | header += string("Connection: Keep-Alive\r\n") + "Keep-Alive: timeout=" + to_string(DEFAULT_KEEP_ALIVE_TIME) + "\r\n"; 659 | } 660 | 661 | // 解析请求文件的类型,供头部字段"Content-Type:"使用 662 | int dot_pos = fileName_.find('.'); 663 | string filetype; 664 | if (dot_pos < 0) 665 | filetype = MimeType::getMime("default"); 666 | else 667 | filetype = MimeType::getMime(fileName_.substr(dot_pos)); 668 | 669 | 670 | // echo test 671 | if (fileName_ == "hello") 672 | { 673 | outBuffer_ = "HTTP/1.1 200 OK\r\nContent-type: text/plain\r\n\r\nHello World"; 674 | return ANALYSIS_SUCCESS; 675 | } 676 | 677 | // 请求是网站图标,返回图标 678 | if (fileName_ == "favicon.ico") 679 | { 680 | header += "Content-Type: image/png\r\n"; 681 | header += "Content-Length: " + to_string(sizeof favicon) + "\r\n"; 682 | header += "Server: LinYa's Web Server\r\n"; 683 | 684 | header += "\r\n"; 685 | outBuffer_ += header; 686 | outBuffer_ += string(favicon, favicon + sizeof favicon); 687 | return ANALYSIS_SUCCESS; 688 | } 689 | 690 | 691 | // 用于获取目标文件的属性,比如是否为目录,文件大小等 692 | struct stat sbuf; 693 | // 目标文件是否是有效文件 694 | if (stat(fileName_.c_str(), &sbuf) < 0) 695 | { 696 | header.clear(); 697 | handleError(fd_, 404, "Not Found!"); 698 | return ANALYSIS_ERROR; 699 | } 700 | header += "Content-Type: " + filetype + "\r\n"; 701 | header += "Content-Length: " + to_string(sbuf.st_size) + "\r\n"; 702 | header += "Server: LinYa's Web Server\r\n"; 703 | // 头部结束 704 | header += "\r\n"; 705 | outBuffer_ += header; 706 | 707 | if (method_ == METHOD_HEAD) 708 | return ANALYSIS_SUCCESS; 709 | 710 | // 打开文件 711 | int src_fd = open(fileName_.c_str(), O_RDONLY, 0); 712 | if (src_fd < 0) 713 | { 714 | outBuffer_.clear(); 715 | handleError(fd_, 404, "Not Found!"); 716 | return ANALYSIS_ERROR; 717 | } 718 | 719 | // 将文件映射到共享内存,返回指向目标内存区域的指针 720 | void *mmapRet = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, src_fd, 0); 721 | close(src_fd); 722 | if (mmapRet == (void *)-1) 723 | { 724 | munmap(mmapRet, sbuf.st_size); 725 | outBuffer_.clear(); 726 | handleError(fd_, 404, "Not Found!"); 727 | return ANALYSIS_ERROR; 728 | } 729 | char *src_addr = static_cast(mmapRet); 730 | // 将共享内存复制到输出缓冲 731 | outBuffer_ += string(src_addr, src_addr + sbuf.st_size); 732 | // 释放内存空间 733 | munmap(mmapRet, sbuf.st_size); 734 | return ANALYSIS_SUCCESS; 735 | } 736 | return ANALYSIS_ERROR; 737 | } 738 | 739 | 740 | // 处理错误 741 | void HttpData::handleError(int fd, int err_num, string short_msg) 742 | { 743 | short_msg = " " + short_msg; 744 | char send_buff[4096]; 745 | string body_buff, header_buff; 746 | body_buff += "哎~出错了"; 747 | body_buff += ""; 748 | body_buff += to_string(err_num) + short_msg; 749 | body_buff += "
LinYa's Web Server\n"; 750 | 751 | header_buff += "HTTP/1.1 " + to_string(err_num) + short_msg + "\r\n"; 752 | header_buff += "Content-Type: text/html\r\n"; 753 | header_buff += "Connection: Close\r\n"; 754 | header_buff += "Content-Length: " + to_string(body_buff.size()) + "\r\n"; 755 | header_buff += "Server: LinYa's Web Server\r\n";; 756 | header_buff += "\r\n"; 757 | // 错误处理不考虑writen不完的情况 758 | sprintf(send_buff, "%s", header_buff.c_str()); 759 | writen(fd, send_buff, strlen(send_buff)); 760 | sprintf(send_buff, "%s", body_buff.c_str()); 761 | writen(fd, send_buff, strlen(send_buff)); 762 | } 763 | 764 | 765 | // 关闭连接 766 | void HttpData::handleClose() 767 | { 768 | connectionState_ = H_DISCONNECTED; 769 | shared_ptr guard(shared_from_this()); 770 | loop_->removeFromPoller(channel_); 771 | } 772 | 773 | 774 | void HttpData::newEvent() 775 | { 776 | channel_->setEvents(DEFAULT_EVENT); 777 | loop_->addToPoller(channel_, DEFAULT_EXPIRED_TIME); 778 | } 779 | -------------------------------------------------------------------------------- /WebServer/HttpData.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "Timer.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | class EventLoop; 14 | class TimerNode; 15 | class Channel; 16 | 17 | // 状态机处理状态 18 | enum ProcessState 19 | { 20 | STATE_PARSE_URI = 1, 21 | STATE_PARSE_HEADERS, 22 | STATE_RECV_BODY, 23 | STATE_ANALYSIS, 24 | STATE_FINISH 25 | }; 26 | 27 | // 28 | enum URIState 29 | { 30 | PARSE_URI_AGAIN = 1, 31 | PARSE_URI_ERROR, 32 | PARSE_URI_SUCCESS, 33 | }; 34 | 35 | enum HeaderState 36 | { 37 | PARSE_HEADER_SUCCESS = 1, 38 | PARSE_HEADER_AGAIN, 39 | PARSE_HEADER_ERROR 40 | }; 41 | 42 | enum AnalysisState 43 | { 44 | ANALYSIS_SUCCESS = 1, 45 | ANALYSIS_ERROR 46 | }; 47 | 48 | enum ParseState 49 | { 50 | H_START = 0, 51 | H_KEY, 52 | H_COLON, 53 | H_SPACES_AFTER_COLON, 54 | H_VALUE, 55 | H_CR, 56 | H_LF, 57 | H_END_CR, 58 | H_END_LF 59 | }; 60 | 61 | enum ConnectionState 62 | { 63 | H_CONNECTED = 0, 64 | H_DISCONNECTING, 65 | H_DISCONNECTED 66 | }; 67 | 68 | enum HttpMethod 69 | { 70 | METHOD_POST = 1, 71 | METHOD_GET, 72 | METHOD_HEAD 73 | }; 74 | 75 | enum HttpVersion 76 | { 77 | HTTP_10 = 1, 78 | HTTP_11 79 | }; 80 | 81 | class MimeType 82 | { 83 | private: 84 | static void init(); 85 | static std::unordered_map mime; 86 | MimeType(); 87 | MimeType(const MimeType &m); 88 | 89 | public: 90 | static std::string getMime(const std::string &suffix); 91 | 92 | private: 93 | static pthread_once_t once_control; 94 | }; 95 | 96 | 97 | class HttpData: public std::enable_shared_from_this 98 | { 99 | public: 100 | HttpData(EventLoop *loop, int connfd); 101 | ~HttpData() { close(fd_); } 102 | void reset(); 103 | void seperateTimer(); // 与关联的定时器分开 104 | void linkTimer(std::shared_ptr mtimer) // 关联定时器,即弱指针指向实际的定时器节点 105 | { 106 | // shared_ptr重载了bool, 但weak_ptr没有 107 | timer_ = mtimer; 108 | } 109 | std::shared_ptr getChannel() { return channel_; } 110 | EventLoop *getLoop() { return loop_; } 111 | void handleClose(); 112 | void newEvent(); 113 | 114 | private: 115 | EventLoop *loop_; 116 | std::shared_ptr channel_; 117 | int fd_; 118 | std::string inBuffer_; // 读缓冲 119 | std::string outBuffer_; // 写缓冲 120 | bool error_; 121 | ConnectionState connectionState_; 122 | 123 | HttpMethod method_; 124 | HttpVersion HTTPVersion_; 125 | std::string fileName_; 126 | std::string path_; 127 | int nowReadPos_; 128 | ProcessState state_; 129 | ParseState hState_; 130 | bool keepAlive_; 131 | std::map headers_; 132 | 133 | // 该连接对应的定时器 134 | std::weak_ptr timer_; 135 | 136 | 137 | void handleRead(); // 核心函数1:读取解析http请求 138 | void handleWrite(); // 核心函数2:写入http响应 139 | void handleConn(); // 140 | void handleError(int fd, int err_num, std::string short_msg); 141 | 142 | URIState parseURI(); 143 | HeaderState parseHeaders(); 144 | AnalysisState analysisRequest(); 145 | }; -------------------------------------------------------------------------------- /WebServer/Main.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "EventLoop.h" 4 | #include "Server.h" 5 | #include "base/Logging.h" 6 | #include 7 | #include 8 | 9 | int main(int argc, char *argv[]) 10 | { 11 | int threadNum = 4; 12 | int port = 80; 13 | std::string logPath = "./WebServer.log"; 14 | 15 | // parse args 16 | // 解析参数 17 | int opt; 18 | const char *str = "t:l:p:"; //选项字符串,单个":"表示该选项有且必须有参数 19 | while ((opt = getopt(argc, argv, str))!= -1) 20 | { 21 | switch (opt) 22 | { 23 | case 't': // -t 线程数 24 | { 25 | threadNum = atoi(optarg); 26 | break; 27 | } 28 | case 'l': // -l 日志文件路径 29 | { 30 | logPath = optarg; 31 | if (logPath.size() < 2 || optarg[0] != '/') 32 | { 33 | printf("logPath should start with \"/\"\n"); 34 | abort(); 35 | } 36 | break; 37 | } 38 | case 'p': // -p 端口号 39 | { 40 | port = atoi(optarg); 41 | break; 42 | } 43 | default: break; 44 | } 45 | } 46 | Logger::setLogFileName(logPath); 47 | // STL库在多线程上应用 48 | #ifndef _PTHREADS 49 | LOG << "_PTHREADS is not defined !"; 50 | #endif 51 | EventLoop mainLoop; // baseLoop只用来接受新连接 52 | Server myHTTPServer(&mainLoop, threadNum, port); // 通过自定义的Server类来处理http 53 | myHTTPServer.start(); // 开启线程池,初始化接收器,在baseLoop中注册接受器Channel 54 | mainLoop.loop(); // 开启主事件循环,用来接受新连接,然后把新连接交给子线程的事件循环处理 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /WebServer/Makefile: -------------------------------------------------------------------------------- 1 | # MAINSOURCE代表含有main入口函数的cpp文件,因为含有测试代码, 2 | # 所以要为多个目标编译,这里把Makefile写的通用了一点, 3 | # 以后加东西Makefile不用做多少改动 4 | MAINSOURCE := Main.cpp base/tests/LoggingTest.cpp tests/HTTPClient.cpp 5 | # MAINOBJS := $(patsubst %.cpp,%.o,$(MAINSOURCE)) 6 | SOURCE := $(wildcard *.cpp base/*.cpp tests/*.cpp) 7 | override SOURCE := $(filter-out $(MAINSOURCE),$(SOURCE)) 8 | OBJS := $(patsubst %.cpp,%.o,$(SOURCE)) 9 | 10 | TARGET := WebServer 11 | CC := g++ 12 | LIBS := -lpthread 13 | INCLUDE:= -I./usr/local/lib 14 | CFLAGS := -std=c++11 -g -Wall -O3 -D_PTHREADS 15 | CXXFLAGS:= $(CFLAGS) 16 | 17 | # Test object 18 | SUBTARGET1 := LoggingTest 19 | SUBTARGET2 := HTTPClient 20 | 21 | .PHONY : objs clean veryclean rebuild all tests debug 22 | all : $(TARGET) $(SUBTARGET1) $(SUBTARGET2) 23 | objs : $(OBJS) 24 | rebuild: veryclean all 25 | 26 | tests : $(SUBTARGET1) $(SUBTARGET2) 27 | clean : 28 | find . -name '*.o' | xargs rm -f 29 | veryclean : 30 | find . -name '*.o' | xargs rm -f 31 | find . -name $(TARGET) | xargs rm -f 32 | find . -name $(SUBTARGET1) | xargs rm -f 33 | find . -name $(SUBTARGET2) | xargs rm -f 34 | debug: 35 | @echo $(SOURCE) 36 | 37 | $(TARGET) : $(OBJS) Main.o 38 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 39 | # $@代表目标,这里是$(TARGET) 40 | 41 | $(SUBTARGET1) : $(OBJS) base/tests/LoggingTest.o 42 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 43 | 44 | $(SUBTARGET2) : $(OBJS) tests/HTTPClient.o 45 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 46 | -------------------------------------------------------------------------------- /WebServer/Makefile.bak: -------------------------------------------------------------------------------- 1 | # @Author Lin Ya 2 | # @Email xxbbb@vip.qq.com 3 | # MAINSOURCE代表含有main入口函数的cpp文件,因为含有测试代码, 4 | # 所以要为多个目标编译,这里把Makefile写的通用了一点, 5 | # 以后加东西Makefile不用做多少改动 6 | MAINSOURCE := Main.cpp base/tests/LoggingTest.cpp tests/HTTPClient.cpp 7 | # MAINOBJS := $(patsubst %.cpp,%.o,$(MAINSOURCE)) 8 | SOURCE := $(wildcard *.cpp base/*.cpp tests/*.cpp) 9 | override SOURCE := $(filter-out $(MAINSOURCE),$(SOURCE)) 10 | OBJS := $(patsubst %.cpp,%.o,$(SOURCE)) 11 | 12 | TARGET := WebServer 13 | CC := g++ 14 | LIBS := -lpthread -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_imgcodecs 15 | INCLUDE:= -I./usr/local/lib 16 | CFLAGS := -std=c++11 -g -Wall -O3 -D_PTHREADS 17 | CXXFLAGS:= $(CFLAGS) 18 | 19 | # Test object 20 | SUBTARGET1 := LoggingTest 21 | SUBTARGET2 := HTTPClient 22 | 23 | .PHONY : objs clean veryclean rebuild all tests debug 24 | all : $(TARGET) $(SUBTARGET1) $(SUBTARGET2) 25 | objs : $(OBJS) 26 | rebuild: veryclean all 27 | 28 | tests : $(SUBTARGET1) $(SUBTARGET2) 29 | clean : 30 | find . -name '*.o' | xargs rm -f 31 | veryclean : 32 | find . -name '*.o' | xargs rm -f 33 | find . -name $(TARGET) | xargs rm -f 34 | find . -name $(SUBTARGET1) | xargs rm -f 35 | find . -name $(SUBTARGET2) | xargs rm -f 36 | debug: 37 | @echo $(SOURCE) 38 | 39 | $(TARGET) : $(OBJS) Main.o 40 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 41 | # $@代表目标,这里是$(TARGET) 42 | 43 | $(SUBTARGET1) : $(OBJS) base/tests/LoggingTest.o 44 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) 45 | 46 | $(SUBTARGET2) : $(OBJS) tests/HTTPClient.o 47 | $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) -------------------------------------------------------------------------------- /WebServer/Server.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Server.h" 4 | #include "base/Logging.h" 5 | #include "Util.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // 构造函数,初始化成员变量loop_、threadNum_、port、started_(false) 12 | Server::Server(EventLoop *loop, int threadNum, int port) 13 | : loop_(loop), 14 | threadNum_(threadNum), 15 | eventLoopThreadPool_(new EventLoopThreadPool(loop_, threadNum)), // 创建线程池 16 | started_(false), 17 | acceptChannel_(new Channel(loop_)), // 接受器Channel 18 | port_(port), 19 | listenFd_(socket_bind_listen(port_)) // 初始化监听描述符 20 | { 21 | acceptChannel_->setFd(listenFd_); // 设置接受器的fd 22 | handle_for_sigpipe(); // 处理SIGPIPE(向读端关闭的管道或socket连接中写数据)信号 23 | if (setSocketNonBlocking(listenFd_) < 0) // 设置fd为非阻塞 24 | { 25 | perror("set socket non block failed"); 26 | abort(); 27 | } 28 | } 29 | 30 | // 开启线程池,初始化接收器,在baseLoop中注册接受器 31 | void Server::start() 32 | { 33 | eventLoopThreadPool_->start(); // 开启线程池 34 | //acceptChannel_->setEvents(EPOLLIN | EPOLLET | EPOLLONESHOT); 35 | 36 | /* 下面这部分原本应该由Acceptor类负责 */ 37 | acceptChannel_->setEvents(EPOLLIN | EPOLLET); // 注册epoll_evevts中events事件 38 | acceptChannel_->setReadHandler(bind(&Server::handNewConn, this)); // 设置acceptChannel_::handleRead()回调函数 39 | acceptChannel_->setConnHandler(bind(&Server::handThisConn, this)); // 设置acceptChannel_::handleConn()回调函数 40 | loop_->addToPoller(acceptChannel_, 0); 41 | 42 | 43 | started_ = true; 44 | } 45 | 46 | // 接受新连接,分配新连接到子线程中 47 | // handNewConn原本应该是由Acceptor负责的,并在Acceptor的handleRead中调用 48 | // 这里用acceptChannel代替了Acceptor,所以在start()函数中acceptChannel_->setReadHandler(bind(&Server::handNewConn, this)) 49 | void Server::handNewConn() 50 | { 51 | struct sockaddr_in client_addr; 52 | memset(&client_addr, 0, sizeof(struct sockaddr_in)); 53 | socklen_t client_addr_len = sizeof(client_addr); 54 | int accept_fd = 0; 55 | while((accept_fd = accept(listenFd_, (struct sockaddr*)&client_addr, &client_addr_len)) > 0) 56 | { 57 | 58 | /* 多线程的核心,轮询调度,从线程池中取出子线程的事件循环,把新连接交由子线程处理 */ 59 | EventLoop *loop = eventLoopThreadPool_->getNextLoop(); 60 | 61 | 62 | 63 | LOG << "New connection from " << inet_ntoa(client_addr.sin_addr) << ":" << ntohs(client_addr.sin_port); 64 | // cout << "new connection" << endl; 65 | // cout << inet_ntoa(client_addr.sin_addr) << endl; 66 | // cout << ntohs(client_addr.sin_port) << endl; 67 | /* 68 | // TCP的保活机制默认是关闭的 69 | int optval = 0; 70 | socklen_t len_optval = 4; 71 | getsockopt(accept_fd, SOL_SOCKET, SO_KEEPALIVE, &optval, &len_optval); 72 | cout << "optval ==" << optval << endl; 73 | */ 74 | // 限制服务器的最大并发连接数 75 | if (accept_fd >= MAXFDS) 76 | { 77 | close(accept_fd); 78 | continue; 79 | } 80 | // 设为非阻塞模式 81 | if (setSocketNonBlocking(accept_fd) < 0) 82 | { 83 | LOG << "Set non block failed!"; 84 | //perror("Set non block failed!"); 85 | return; 86 | } 87 | 88 | setSocketNodelay(accept_fd); 89 | //setSocketNoLinger(accept_fd); 90 | 91 | // 新建的连接由HttpData类管理,这里的HttpData相当于TcpConnect 92 | shared_ptr req_info(new HttpData(loop, accept_fd)); 93 | req_info->getChannel()->setHolder(req_info); 94 | // 调用newEvent将req_info中的channel注册到IO子线程 95 | // 感觉这里应该调用loop->runInLoop() 96 | loop->queueInLoop(std::bind(&HttpData::newEvent, req_info)); 97 | } 98 | acceptChannel_->setEvents(EPOLLIN | EPOLLET); // 再次设置acceptChannel的事件 99 | } -------------------------------------------------------------------------------- /WebServer/Server.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "EventLoop.h" 5 | #include "Channel.h" 6 | #include "EventLoopThreadPool.h" 7 | #include 8 | 9 | // HttpServer服务器类 10 | class Server 11 | { 12 | public: 13 | /* 14 | muduo的做法是实现一个底层的TcpServer类和TcpConnection类,TcpServer中有一个TcpConnection指针, 15 | 然后在自定义的HttpServer类的构造函数中往TcpServer对象中注册回调函数, 16 | 这里做法相当于把TcpServer类揉进了本类HttpServer的实现中, 17 | 所以没有了注册回调函数的步骤,直接处理新连接newConnection,和本连接Connection 18 | */ 19 | Server(EventLoop *loop, int threadNum, int port); 20 | ~Server() { } 21 | EventLoop* getLoop() const { return loop_; } // 返回EventLoop对象指针 22 | void start(); // muduo这里调用TcpServer类的start()方法,此处是实现TcpServer类的start()方法 23 | void handNewConn(); // 处理新连接 24 | void handThisConn() { loop_->updatePoller(acceptChannel_); } // 处理连接 25 | 26 | private: 27 | /* 28 | TcpServer类中拥有一个主事件循环对象EventLoop、一个接受器Acceptor、一个线程池对象EventLoopThreadPool 29 | */ 30 | EventLoop *loop_; // 只用来接受新连接, 31 | int threadNum_; // 多线程线程数 32 | std::unique_ptr eventLoopThreadPool_; // 线程池unique指针,创建IO线程池,把TcpConnection分派到不同的EventLoop上 33 | bool started_; 34 | std::shared_ptr acceptChannel_; // 接受器指针,相当于Acceptor,用于服务器接受连接,用来获取新连接的fd 35 | int port_; // 端口 36 | int listenFd_; // 监听描述符 37 | static const int MAXFDS = 100000; // 最大描述符限制 38 | }; -------------------------------------------------------------------------------- /WebServer/ThreadPool.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | 4 | 5 | // This file has not been used 6 | #include "ThreadPool.h" 7 | 8 | pthread_mutex_t ThreadPool::lock = PTHREAD_MUTEX_INITIALIZER; 9 | pthread_cond_t ThreadPool::notify = PTHREAD_COND_INITIALIZER; 10 | std::vector ThreadPool::threads; 11 | std::vector ThreadPool::queue; 12 | int ThreadPool::thread_count = 0; 13 | int ThreadPool::queue_size = 0; 14 | int ThreadPool::head = 0; 15 | int ThreadPool::tail = 0; 16 | int ThreadPool::count = 0; 17 | int ThreadPool::shutdown = 0; 18 | int ThreadPool::started = 0; 19 | 20 | int ThreadPool::threadpool_create(int _thread_count, int _queue_size) 21 | { 22 | bool err = false; 23 | do 24 | { 25 | if(_thread_count <= 0 || _thread_count > MAX_THREADS || _queue_size <= 0 || _queue_size > MAX_QUEUE) 26 | { 27 | _thread_count = 4; 28 | _queue_size = 1024; 29 | } 30 | 31 | thread_count = 0; 32 | queue_size = _queue_size; 33 | head = tail = count = 0; 34 | shutdown = started = 0; 35 | 36 | threads.resize(_thread_count); 37 | queue.resize(_queue_size); 38 | 39 | /* Start worker threads */ 40 | for(int i = 0; i < _thread_count; ++i) 41 | { 42 | if(pthread_create(&threads[i], NULL, threadpool_thread, (void*)(0)) != 0) 43 | { 44 | //threadpool_destroy(pool, 0); 45 | return -1; 46 | } 47 | ++thread_count; 48 | ++started; 49 | } 50 | } while(false); 51 | 52 | if (err) 53 | { 54 | //threadpool_free(pool); 55 | return -1; 56 | } 57 | return 0; 58 | } 59 | 60 | int ThreadPool::threadpool_add(std::shared_ptr args, std::function)> fun) 61 | { 62 | int next, err = 0; 63 | if(pthread_mutex_lock(&lock) != 0) 64 | return THREADPOOL_LOCK_FAILURE; 65 | do 66 | { 67 | next = (tail + 1) % queue_size; 68 | // 队列满 69 | if(count == queue_size) 70 | { 71 | err = THREADPOOL_QUEUE_FULL; 72 | break; 73 | } 74 | // 已关闭 75 | if(shutdown) 76 | { 77 | err = THREADPOOL_SHUTDOWN; 78 | break; 79 | } 80 | queue[tail].fun = fun; 81 | queue[tail].args = args; 82 | tail = next; 83 | ++count; 84 | 85 | /* pthread_cond_broadcast */ 86 | if(pthread_cond_signal(¬ify) != 0) 87 | { 88 | err = THREADPOOL_LOCK_FAILURE; 89 | break; 90 | } 91 | } while(false); 92 | 93 | if(pthread_mutex_unlock(&lock) != 0) 94 | err = THREADPOOL_LOCK_FAILURE; 95 | return err; 96 | } 97 | 98 | 99 | int ThreadPool::threadpool_destroy(ShutDownOption shutdown_option) 100 | { 101 | printf("Thread pool destroy !\n"); 102 | int i, err = 0; 103 | 104 | if(pthread_mutex_lock(&lock) != 0) 105 | { 106 | return THREADPOOL_LOCK_FAILURE; 107 | } 108 | do 109 | { 110 | if(shutdown) { 111 | err = THREADPOOL_SHUTDOWN; 112 | break; 113 | } 114 | shutdown = shutdown_option; 115 | 116 | if((pthread_cond_broadcast(¬ify) != 0) || 117 | (pthread_mutex_unlock(&lock) != 0)) { 118 | err = THREADPOOL_LOCK_FAILURE; 119 | break; 120 | } 121 | 122 | for(i = 0; i < thread_count; ++i) 123 | { 124 | if(pthread_join(threads[i], NULL) != 0) 125 | { 126 | err = THREADPOOL_THREAD_FAILURE; 127 | } 128 | } 129 | } while(false); 130 | 131 | if(!err) 132 | { 133 | threadpool_free(); 134 | } 135 | return err; 136 | } 137 | 138 | int ThreadPool::threadpool_free() 139 | { 140 | if(started > 0) 141 | return -1; 142 | pthread_mutex_lock(&lock); 143 | pthread_mutex_destroy(&lock); 144 | pthread_cond_destroy(¬ify); 145 | return 0; 146 | } 147 | 148 | 149 | void *ThreadPool::threadpool_thread(void *args) 150 | { 151 | while (true) 152 | { 153 | ThreadPoolTask task; 154 | pthread_mutex_lock(&lock); 155 | while((count == 0) && (!shutdown)) 156 | { 157 | pthread_cond_wait(¬ify, &lock); 158 | } 159 | if((shutdown == immediate_shutdown) || 160 | ((shutdown == graceful_shutdown) && (count == 0))) 161 | { 162 | break; 163 | } 164 | task.fun = queue[head].fun; 165 | task.args = queue[head].args; 166 | queue[head].fun = NULL; 167 | queue[head].args.reset(); 168 | head = (head + 1) % queue_size; 169 | --count; 170 | pthread_mutex_unlock(&lock); 171 | (task.fun)(task.args); 172 | } 173 | --started; 174 | pthread_mutex_unlock(&lock); 175 | printf("This threadpool thread finishs!\n"); 176 | pthread_exit(NULL); 177 | return(NULL); 178 | } -------------------------------------------------------------------------------- /WebServer/ThreadPool.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | 4 | // This file has not been used 5 | #pragma once 6 | #include "Channel.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | const int THREADPOOL_INVALID = -1; 13 | const int THREADPOOL_LOCK_FAILURE = -2; 14 | const int THREADPOOL_QUEUE_FULL = -3; 15 | const int THREADPOOL_SHUTDOWN = -4; 16 | const int THREADPOOL_THREAD_FAILURE = -5; 17 | const int THREADPOOL_GRACEFUL = 1; 18 | 19 | const int MAX_THREADS = 1024; 20 | const int MAX_QUEUE = 65535; 21 | 22 | typedef enum 23 | { 24 | immediate_shutdown = 1, 25 | graceful_shutdown = 2 26 | } ShutDownOption; 27 | 28 | struct ThreadPoolTask 29 | { 30 | std::function)> fun; 31 | std::shared_ptr args; 32 | }; 33 | 34 | 35 | class ThreadPool 36 | { 37 | private: 38 | static pthread_mutex_t lock; 39 | static pthread_cond_t notify; 40 | 41 | static std::vector threads; 42 | static std::vector queue; 43 | static int thread_count; 44 | static int queue_size; 45 | static int head; 46 | // tail 指向尾节点的下一节点 47 | static int tail; 48 | static int count; 49 | static int shutdown; 50 | static int started; 51 | public: 52 | static int threadpool_create(int _thread_count, int _queue_size); 53 | static int threadpool_add(std::shared_ptr args, std::function)> fun); 54 | static int threadpool_destroy(ShutDownOption shutdown_option = graceful_shutdown); 55 | static int threadpool_free(); 56 | static void *threadpool_thread(void *args); 57 | }; 58 | -------------------------------------------------------------------------------- /WebServer/Timer.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Timer.h" 4 | #include 5 | #include 6 | #include 7 | 8 | 9 | TimerNode::TimerNode(std::shared_ptr requestData, int timeout) 10 | : deleted_(false), 11 | SPHttpData(requestData) 12 | { 13 | // 获取当前时间 14 | struct timeval now; 15 | gettimeofday(&now, NULL); 16 | // 计算过期时间: 17 | // 以毫秒计 18 | expiredTime_ = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout; // 过期时间 19 | } 20 | 21 | // 定时器在析构的时候关闭连接 这里定时器的功能很单一 22 | TimerNode::~TimerNode() 23 | { 24 | if (SPHttpData) 25 | SPHttpData->handleClose(); 26 | } 27 | 28 | TimerNode::TimerNode(TimerNode &tn): 29 | SPHttpData(tn.SPHttpData) 30 | { } 31 | 32 | 33 | void TimerNode::update(int timeout) 34 | { 35 | struct timeval now; 36 | gettimeofday(&now, NULL); 37 | expiredTime_ = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)) + timeout; 38 | } 39 | 40 | bool TimerNode::isValid() // 判断定时器是否超时 41 | { 42 | struct timeval now; 43 | gettimeofday(&now, NULL); 44 | size_t temp = (((now.tv_sec % 10000) * 1000) + (now.tv_usec / 1000)); 45 | if (temp < expiredTime_) 46 | return true; 47 | else 48 | { 49 | this->setDeleted(); 50 | return false; 51 | } 52 | } 53 | 54 | // 将定时器设置为删除的 55 | void TimerNode::clearReq() 56 | { 57 | SPHttpData.reset(); 58 | this->setDeleted(); 59 | } 60 | 61 | 62 | TimerManager::TimerManager() 63 | { } 64 | 65 | TimerManager::~TimerManager() 66 | { } 67 | 68 | // 添加定时器,new一个timerNode节点,并与相应的HttpData对象关联 69 | void TimerManager::addTimer(std::shared_ptr SPHttpData, int timeout) 70 | { 71 | SPTimerNode new_node(new TimerNode(SPHttpData, timeout)); 72 | timerNodeQueue.push(new_node); 73 | SPHttpData->linkTimer(new_node); 74 | } 75 | 76 | 77 | /* 处理逻辑是这样的 78 | 因为(1) 优先队列不支持随机访问 79 | (2) 即使支持,随机删除某节点后破坏了堆的结构,需要重新更新堆结构。 80 | 所以对于被置为deleted的时间节点,会延迟到它(1)超时 或 (2)它前面的节点都被删除时,它才会被删除。 81 | 一个点被置为deleted,它最迟会在TIMER_TIME_OUT时间后被删除。 82 | 这样做有两个好处: 83 | (1) 第一个好处是不需要遍历优先队列,省时。 84 | (2) 第二个好处是给超时时间一个容忍的时间,就是设定的超时时间是删除的下限(并不是一到超时时间就立即删除),如果监听的请求在超时后的下一次请求中又一次出现了, 85 | 就不用再重新申请RequestData节点了,这样可以继续重复利用前面的RequestData,减少了一次delete和一次new的时间。 86 | */ 87 | 88 | void TimerManager::handleExpiredEvent() 89 | { 90 | //MutexLockGuard locker(lock); 91 | // 队列中非空就处理,直到队列头未超时 92 | while (!timerNodeQueue.empty()) 93 | { 94 | SPTimerNode ptimer_now = timerNodeQueue.top(); 95 | if (ptimer_now->isDeleted()) // 判断队列头是否已经是被标记为删除掉的 96 | timerNodeQueue.pop(); // 就删除 97 | else if (ptimer_now->isValid() == false) // 判断定时器是否超时 98 | timerNodeQueue.pop(); 99 | else 100 | break; 101 | } 102 | } -------------------------------------------------------------------------------- /WebServer/Timer.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "HttpData.h" 5 | #include "base/noncopyable.h" 6 | #include "base/MutexLock.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | class HttpData; 13 | 14 | /* 15 | 定时器实现 16 | 17 | */ 18 | // 定时器节点 timeout的单位是毫秒 19 | class TimerNode 20 | { 21 | public: 22 | TimerNode(std::shared_ptr requestData, int timeout); 23 | ~TimerNode(); 24 | TimerNode(TimerNode &tn); 25 | void update(int timeout); 26 | bool isValid(); 27 | void clearReq(); 28 | void setDeleted() { deleted_ = true; } 29 | bool isDeleted() const { return deleted_; } 30 | size_t getExpTime() const { return expiredTime_; } 31 | 32 | private: 33 | bool deleted_; 34 | size_t expiredTime_; 35 | std::shared_ptr SPHttpData; 36 | }; 37 | 38 | struct TimerCmp 39 | { 40 | bool operator()(std::shared_ptr &a, std::shared_ptr &b) const 41 | { 42 | return a->getExpTime() > b->getExpTime(); 43 | } 44 | }; 45 | 46 | 47 | 48 | // 最小堆实现定时器 49 | class TimerManager 50 | { 51 | public: 52 | TimerManager(); 53 | ~TimerManager(); 54 | void addTimer(std::shared_ptr SPHttpData, int timeout); 55 | void handleExpiredEvent(); 56 | 57 | private: 58 | typedef std::shared_ptr SPTimerNode; // 将定时节点的指针 59 | std::priority_queue, TimerCmp> timerNodeQueue; // 用优先队列实现定时器 60 | //MutexLock lock; 61 | }; -------------------------------------------------------------------------------- /WebServer/Util.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Util.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | const int MAX_BUFF = 4096; 14 | 15 | // 读n个字节到buff中,返回实际读出的字节数 16 | ssize_t readn(int fd, void *buff, size_t n) 17 | { 18 | size_t nleft = n; 19 | ssize_t nread = 0; 20 | ssize_t readSum = 0; 21 | char *ptr = (char*)buff; 22 | while (nleft > 0) 23 | { 24 | if ((nread = read(fd, ptr, nleft)) < 0) 25 | { 26 | if (errno == EINTR) // 中断 27 | nread = 0; 28 | else if (errno == EAGAIN) // 非阻塞要读到EAGAIN为止 29 | { 30 | return readSum; 31 | } 32 | else 33 | { 34 | return -1; 35 | } 36 | } 37 | else if (nread == 0) 38 | break; 39 | readSum += nread; 40 | nleft -= nread; 41 | ptr += nread; 42 | } 43 | return readSum; 44 | } 45 | 46 | // 读数据到字符串缓冲区inBuffer,zero标志着是否读入了数据 47 | ssize_t readn(int fd, std::string &inBuffer, bool &zero) 48 | { 49 | ssize_t nread = 0; 50 | ssize_t readSum = 0; 51 | while (true) 52 | { 53 | char buff[MAX_BUFF]; 54 | if ((nread = read(fd, buff, MAX_BUFF)) < 0) 55 | { 56 | if (errno == EINTR) 57 | continue; 58 | else if (errno == EAGAIN) 59 | { 60 | return readSum; 61 | } 62 | else 63 | { 64 | perror("read error"); 65 | return -1; 66 | } 67 | } 68 | else if (nread == 0) 69 | { 70 | //printf("redsum = %d\n", readSum); 71 | zero = true; 72 | break; 73 | } 74 | //printf("before inBuffer.size() = %d\n", inBuffer.size()); 75 | //printf("nread = %d\n", nread); 76 | readSum += nread; 77 | //buff += nread; 78 | inBuffer += std::string(buff, buff + nread); 79 | //printf("after inBuffer.size() = %d\n", inBuffer.size()); 80 | } 81 | return readSum; 82 | } 83 | 84 | // 读数据到字符串缓冲区inBuffer 85 | ssize_t readn(int fd, std::string &inBuffer) 86 | { 87 | ssize_t nread = 0; 88 | ssize_t readSum = 0; 89 | while (true) 90 | { 91 | char buff[MAX_BUFF]; 92 | if ((nread = read(fd, buff, MAX_BUFF)) < 0) 93 | { 94 | if (errno == EINTR) 95 | continue; 96 | else if (errno == EAGAIN) 97 | { 98 | return readSum; 99 | } 100 | else 101 | { 102 | perror("read error"); 103 | return -1; 104 | } 105 | } 106 | else if (nread == 0) 107 | { 108 | //printf("redsum = %d\n", readSum); 109 | break; 110 | } 111 | //printf("before inBuffer.size() = %d\n", inBuffer.size()); 112 | //printf("nread = %d\n", nread); 113 | readSum += nread; 114 | //buff += nread; 115 | inBuffer += std::string(buff, buff + nread); 116 | //printf("after inBuffer.size() = %d\n", inBuffer.size()); 117 | } 118 | return readSum; 119 | } 120 | 121 | // 将buff中的数据写入描述符,返回实际写入的字节数 122 | ssize_t writen(int fd, void *buff, size_t n) 123 | { 124 | size_t nleft = n; 125 | ssize_t nwritten = 0; 126 | ssize_t writeSum = 0; 127 | char *ptr = (char*)buff; 128 | while (nleft > 0) 129 | { 130 | if ((nwritten = write(fd, ptr, nleft)) <= 0) 131 | { 132 | if (nwritten < 0) 133 | { 134 | if (errno == EINTR) 135 | { 136 | nwritten = 0; 137 | continue; 138 | } 139 | else if (errno == EAGAIN) 140 | { 141 | return writeSum; 142 | } 143 | else 144 | return -1; 145 | } 146 | } 147 | writeSum += nwritten; 148 | nleft -= nwritten; 149 | ptr += nwritten; 150 | } 151 | return writeSum; 152 | } 153 | 154 | 155 | // 将sbuff中的数据写入描述符,返回实际写入的字节数 156 | ssize_t writen(int fd, std::string &sbuff) 157 | { 158 | size_t nleft = sbuff.size(); 159 | ssize_t nwritten = 0; 160 | ssize_t writeSum = 0; 161 | const char *ptr = sbuff.c_str(); 162 | while (nleft > 0) 163 | { 164 | if ((nwritten = write(fd, ptr, nleft)) <= 0) 165 | { 166 | if (nwritten < 0) 167 | { 168 | if (errno == EINTR) 169 | { 170 | nwritten = 0; 171 | continue; 172 | } 173 | else if (errno == EAGAIN) 174 | break; 175 | else 176 | return -1; 177 | } 178 | } 179 | writeSum += nwritten; 180 | nleft -= nwritten; 181 | ptr += nwritten; 182 | } 183 | if (writeSum == static_cast(sbuff.size())) 184 | sbuff.clear(); 185 | else 186 | sbuff = sbuff.substr(writeSum); 187 | return writeSum; 188 | } 189 | 190 | // 处理SIGPIPE(向读端关闭的管道或socket连接中写数据)信号 191 | void handle_for_sigpipe() 192 | { 193 | struct sigaction sa; 194 | memset(&sa, '\0', sizeof(sa)); 195 | sa.sa_handler = SIG_IGN; 196 | sa.sa_flags = 0; 197 | if(sigaction(SIGPIPE, &sa, NULL)) 198 | return; 199 | } 200 | 201 | int setSocketNonBlocking(int fd) 202 | { 203 | int flag = fcntl(fd, F_GETFL, 0); 204 | if(flag == -1) 205 | return -1; 206 | 207 | flag |= O_NONBLOCK; 208 | if(fcntl(fd, F_SETFL, flag) == -1) 209 | return -1; 210 | return 0; 211 | } 212 | 213 | void setSocketNodelay(int fd) 214 | { 215 | int enable = 1; 216 | setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)); 217 | } 218 | 219 | void setSocketNoLinger(int fd) 220 | { 221 | struct linger linger_; 222 | linger_.l_onoff = 1; 223 | linger_.l_linger = 30; 224 | setsockopt(fd, SOL_SOCKET, SO_LINGER,(const char *) &linger_, sizeof(linger_)); 225 | } 226 | 227 | // 关闭函数 228 | void shutDownWR(int fd) 229 | { 230 | shutdown(fd, SHUT_WR); 231 | //printf("shutdown\n"); 232 | } 233 | 234 | int socket_bind_listen(int port) 235 | { 236 | // 检查port值,取正确区间范围 237 | if (port < 0 || port > 65535) 238 | return -1; 239 | 240 | // 创建socket(IPv4 + TCP),返回监听描述符 241 | int listen_fd = 0; 242 | if((listen_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 243 | return -1; 244 | 245 | // 消除bind时"Address already in use"错误 246 | int optval = 1; 247 | if(setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) 248 | return -1; 249 | 250 | // 设置服务器IP和Port,和监听描述副绑定 251 | struct sockaddr_in server_addr; 252 | bzero((char*)&server_addr, sizeof(server_addr)); 253 | server_addr.sin_family = AF_INET; 254 | server_addr.sin_addr.s_addr = htonl(INADDR_ANY); 255 | server_addr.sin_port = htons((unsigned short)port); 256 | if(bind(listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) 257 | return -1; 258 | 259 | // 开始监听,最大等待队列长为LISTENQ 260 | if(listen(listen_fd, 2048) == -1) 261 | return -1; 262 | 263 | // 无效监听描述符 264 | if(listen_fd == -1) 265 | { 266 | close(listen_fd); 267 | return -1; 268 | } 269 | return listen_fd; 270 | } -------------------------------------------------------------------------------- /WebServer/Util.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | #include 6 | 7 | ssize_t readn(int fd, void *buff, size_t n); 8 | ssize_t readn(int fd, std::string &inBuffer, bool &zero); 9 | ssize_t readn(int fd, std::string &inBuffer); 10 | ssize_t writen(int fd, void *buff, size_t n); 11 | ssize_t writen(int fd, std::string &sbuff); 12 | void handle_for_sigpipe(); 13 | int setSocketNonBlocking(int fd); 14 | void setSocketNodelay(int fd); 15 | void setSocketNoLinger(int fd); 16 | void shutDownWR(int fd); 17 | int socket_bind_listen(int port); -------------------------------------------------------------------------------- /WebServer/base/AsyncLogging.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "AsyncLogging.h" 4 | #include "LogFile.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | 11 | AsyncLogging::AsyncLogging(std::string logFileName_,int flushInterval) 12 | : flushInterval_(flushInterval), 13 | running_(false), 14 | basename_(logFileName_), 15 | thread_(std::bind(&AsyncLogging::threadFunc, this), "Logging"), 16 | mutex_(), 17 | cond_(mutex_), 18 | currentBuffer_(new Buffer), 19 | nextBuffer_(new Buffer), 20 | buffers_(), 21 | latch_(1) 22 | { 23 | assert(logFileName_.size() > 1); 24 | currentBuffer_->bzero(); 25 | nextBuffer_->bzero(); 26 | buffers_.reserve(16); 27 | } 28 | 29 | void AsyncLogging::append(const char* logline, int len) 30 | { 31 | MutexLockGuard lock(mutex_); 32 | if (currentBuffer_->avail() > len) 33 | currentBuffer_->append(logline, len); 34 | else 35 | { 36 | buffers_.push_back(currentBuffer_); 37 | currentBuffer_.reset(); 38 | if (nextBuffer_) 39 | currentBuffer_ = std::move(nextBuffer_); 40 | else 41 | currentBuffer_.reset(new Buffer); 42 | currentBuffer_->append(logline, len); 43 | cond_.notify(); 44 | } 45 | } 46 | 47 | void AsyncLogging::threadFunc() 48 | { 49 | assert(running_ == true); 50 | latch_.countDown(); 51 | LogFile output(basename_); 52 | BufferPtr newBuffer1(new Buffer); 53 | BufferPtr newBuffer2(new Buffer); 54 | newBuffer1->bzero(); 55 | newBuffer2->bzero(); 56 | BufferVector buffersToWrite; 57 | buffersToWrite.reserve(16); 58 | while (running_) 59 | { 60 | assert(newBuffer1 && newBuffer1->length() == 0); 61 | assert(newBuffer2 && newBuffer2->length() == 0); 62 | assert(buffersToWrite.empty()); 63 | 64 | { 65 | MutexLockGuard lock(mutex_); 66 | if (buffers_.empty()) // unusual usage! 67 | { 68 | cond_.waitForSeconds(flushInterval_); 69 | } 70 | buffers_.push_back(currentBuffer_); 71 | currentBuffer_.reset(); 72 | 73 | currentBuffer_ = std::move(newBuffer1); 74 | buffersToWrite.swap(buffers_); 75 | if (!nextBuffer_) 76 | { 77 | nextBuffer_ = std::move(newBuffer2); 78 | } 79 | } 80 | 81 | assert(!buffersToWrite.empty()); 82 | 83 | if (buffersToWrite.size() > 25) 84 | { 85 | //char buf[256]; 86 | // snprintf(buf, sizeof buf, "Dropped log messages at %s, %zd larger buffers\n", 87 | // Timestamp::now().toFormattedString().c_str(), 88 | // buffersToWrite.size()-2); 89 | //fputs(buf, stderr); 90 | //output.append(buf, static_cast(strlen(buf))); 91 | buffersToWrite.erase(buffersToWrite.begin()+2, buffersToWrite.end()); 92 | } 93 | 94 | for (size_t i = 0; i < buffersToWrite.size(); ++i) 95 | { 96 | // FIXME: use unbuffered stdio FILE ? or use ::writev ? 97 | output.append(buffersToWrite[i]->data(), buffersToWrite[i]->length()); 98 | } 99 | 100 | if (buffersToWrite.size() > 2) 101 | { 102 | // drop non-bzero-ed buffers, avoid trashing 103 | buffersToWrite.resize(2); 104 | } 105 | 106 | if (!newBuffer1) 107 | { 108 | assert(!buffersToWrite.empty()); 109 | newBuffer1 = buffersToWrite.back(); 110 | buffersToWrite.pop_back(); 111 | newBuffer1->reset(); 112 | } 113 | 114 | if (!newBuffer2) 115 | { 116 | assert(!buffersToWrite.empty()); 117 | newBuffer2 = buffersToWrite.back(); 118 | buffersToWrite.pop_back(); 119 | newBuffer2->reset(); 120 | } 121 | 122 | buffersToWrite.clear(); 123 | output.flush(); 124 | } 125 | output.flush(); 126 | } 127 | -------------------------------------------------------------------------------- /WebServer/base/AsyncLogging.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "CountDownLatch.h" 5 | #include "MutexLock.h" 6 | #include "Thread.h" 7 | #include "LogStream.h" 8 | #include "noncopyable.h" 9 | #include 10 | #include 11 | #include 12 | 13 | class AsyncLogging : noncopyable 14 | { 15 | public: 16 | AsyncLogging(const std::string basename, int flushInterval = 2); 17 | ~AsyncLogging() 18 | { 19 | if (running_) 20 | stop(); 21 | } 22 | void append(const char* logline, int len); 23 | 24 | void start() 25 | { 26 | running_ = true; 27 | thread_.start(); 28 | latch_.wait(); 29 | } 30 | 31 | void stop() 32 | { 33 | running_ = false; 34 | cond_.notify(); 35 | thread_.join(); 36 | } 37 | 38 | 39 | private: 40 | void threadFunc(); 41 | typedef FixedBuffer Buffer; 42 | typedef std::vector> BufferVector; 43 | typedef std::shared_ptr BufferPtr; 44 | const int flushInterval_; 45 | bool running_; 46 | std::string basename_; 47 | Thread thread_; 48 | MutexLock mutex_; 49 | Condition cond_; 50 | BufferPtr currentBuffer_; 51 | BufferPtr nextBuffer_; 52 | BufferVector buffers_; 53 | CountDownLatch latch_; 54 | }; -------------------------------------------------------------------------------- /WebServer/base/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(LIB_SRC 2 | AsyncLogging.cpp 3 | CountDownLatch.cpp 4 | FileUtil.cpp 5 | LogFile.cpp 6 | Logging.cpp 7 | LogStream.cpp 8 | Thread.cpp 9 | ) 10 | 11 | add_library(libserver_base ${LIB_SRC}) 12 | target_link_libraries(libserver_base pthread rt) 13 | 14 | set_target_properties(libserver_base PROPERTIES OUTPUT_NAME "server_base") 15 | 16 | add_subdirectory(tests) -------------------------------------------------------------------------------- /WebServer/base/Condition.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "noncopyable.h" 5 | #include "MutexLock.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | // 封装条件变量 14 | class Condition: noncopyable 15 | { 16 | public: 17 | explicit Condition(MutexLock &_mutex): 18 | mutex(_mutex) 19 | { 20 | pthread_cond_init(&cond, NULL); 21 | } 22 | ~Condition() 23 | { 24 | pthread_cond_destroy(&cond); 25 | } 26 | void wait() 27 | { 28 | pthread_cond_wait(&cond, mutex.get()); 29 | } 30 | void notify() 31 | { 32 | pthread_cond_signal(&cond); 33 | } 34 | void notifyAll() 35 | { 36 | pthread_cond_broadcast(&cond); 37 | } 38 | bool waitForSeconds(int seconds) 39 | { 40 | struct timespec abstime; 41 | clock_gettime(CLOCK_REALTIME, &abstime); 42 | abstime.tv_sec += static_cast(seconds); 43 | return ETIMEDOUT == pthread_cond_timedwait(&cond, mutex.get(), &abstime); 44 | } 45 | private: 46 | MutexLock &mutex; 47 | pthread_cond_t cond; 48 | }; -------------------------------------------------------------------------------- /WebServer/base/CountDownLatch.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "CountDownLatch.h" 4 | 5 | CountDownLatch::CountDownLatch(int count) 6 | : mutex_(), 7 | condition_(mutex_), 8 | count_(count) 9 | { } 10 | 11 | void CountDownLatch::wait() 12 | { 13 | MutexLockGuard lock(mutex_); 14 | while (count_ > 0) 15 | condition_.wait(); 16 | } 17 | 18 | void CountDownLatch::countDown() 19 | { 20 | MutexLockGuard lock(mutex_); 21 | --count_; 22 | if (count_ == 0) 23 | condition_.notifyAll(); 24 | } -------------------------------------------------------------------------------- /WebServer/base/CountDownLatch.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "Condition.h" 5 | #include "MutexLock.h" 6 | #include "noncopyable.h" 7 | 8 | // CountDownLatch的主要作用是确保Thread中传进去的func真的启动了以后 9 | // 外层的start才返回 10 | class CountDownLatch : noncopyable 11 | { 12 | public: 13 | explicit CountDownLatch(int count); 14 | void wait(); 15 | void countDown(); 16 | 17 | private: 18 | mutable MutexLock mutex_; 19 | Condition condition_; 20 | int count_; 21 | }; -------------------------------------------------------------------------------- /WebServer/base/CurrentThread.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include 5 | 6 | 7 | namespace CurrentThread 8 | { 9 | // internal 10 | extern __thread int t_cachedTid; 11 | extern __thread char t_tidString[32]; 12 | extern __thread int t_tidStringLength; 13 | extern __thread const char* t_threadName; 14 | void cacheTid(); 15 | inline int tid() 16 | { 17 | if (__builtin_expect(t_cachedTid == 0, 0)) 18 | { 19 | cacheTid(); 20 | } 21 | return t_cachedTid; 22 | } 23 | 24 | inline const char* tidString() // for logging 25 | { 26 | return t_tidString; 27 | } 28 | 29 | inline int tidStringLength() // for logging 30 | { 31 | return t_tidStringLength; 32 | } 33 | 34 | inline const char* name() 35 | { 36 | return t_threadName; 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /WebServer/base/FileUtil.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "FileUtil.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | 13 | AppendFile::AppendFile(string filename) 14 | : fp_(fopen(filename.c_str(), "ae")) 15 | { 16 | // 用户提供缓冲区 17 | setbuffer(fp_, buffer_, sizeof buffer_); 18 | } 19 | 20 | AppendFile::~AppendFile() 21 | { 22 | fclose(fp_); 23 | } 24 | 25 | void AppendFile::append(const char* logline, const size_t len) 26 | { 27 | size_t n = this->write(logline, len); 28 | size_t remain = len - n; 29 | while (remain > 0) 30 | { 31 | size_t x = this->write(logline + n, remain); 32 | if (x == 0) 33 | { 34 | int err = ferror(fp_); 35 | if (err) 36 | fprintf(stderr, "AppendFile::append() failed !\n"); 37 | break; 38 | } 39 | n += x; 40 | remain = len - n; 41 | } 42 | } 43 | 44 | void AppendFile::flush() 45 | { 46 | fflush(fp_); 47 | } 48 | 49 | size_t AppendFile::write(const char* logline, size_t len) 50 | { 51 | return fwrite_unlocked(logline, 1, len, fp_); 52 | } -------------------------------------------------------------------------------- /WebServer/base/FileUtil.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "noncopyable.h" 5 | #include 6 | 7 | class AppendFile : noncopyable 8 | { 9 | public: 10 | explicit AppendFile(std::string filename); 11 | ~AppendFile(); 12 | // append 会向文件写 13 | void append(const char *logline, const size_t len); 14 | void flush(); 15 | 16 | private: 17 | size_t write(const char *logline, size_t len); 18 | FILE* fp_; 19 | char buffer_[64*1024]; 20 | }; -------------------------------------------------------------------------------- /WebServer/base/LogFile.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "LogFile.h" 4 | #include "FileUtil.h" 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace std; 10 | 11 | 12 | LogFile::LogFile(const string& basename, int flushEveryN) 13 | : basename_(basename), 14 | flushEveryN_(flushEveryN), 15 | count_(0), 16 | mutex_(new MutexLock) 17 | { 18 | //assert(basename.find('/') >= 0); 19 | file_.reset(new AppendFile(basename)); 20 | } 21 | 22 | LogFile::~LogFile() 23 | { } 24 | 25 | void LogFile::append(const char* logline, int len) 26 | { 27 | MutexLockGuard lock(*mutex_); 28 | append_unlocked(logline, len); 29 | } 30 | 31 | void LogFile::flush() 32 | { 33 | MutexLockGuard lock(*mutex_); 34 | file_->flush(); 35 | } 36 | 37 | void LogFile::append_unlocked(const char* logline, int len) 38 | { 39 | file_->append(logline, len); 40 | ++count_; 41 | if (count_ >= flushEveryN_) 42 | { 43 | count_ = 0; 44 | file_->flush(); 45 | } 46 | } -------------------------------------------------------------------------------- /WebServer/base/LogFile.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "FileUtil.h" 5 | #include "MutexLock.h" 6 | #include "noncopyable.h" 7 | #include 8 | #include 9 | 10 | // TODO 提供自动归档功能 11 | class LogFile : noncopyable 12 | { 13 | public: 14 | // 每被append flushEveryN次,flush一下,会往文件写,只不过,文件也是带缓冲区的 15 | LogFile(const std::string& basename, int flushEveryN = 1024); 16 | ~LogFile(); 17 | 18 | void append(const char* logline, int len); 19 | void flush(); 20 | bool rollFile(); 21 | 22 | private: 23 | void append_unlocked(const char* logline, int len); 24 | 25 | const std::string basename_; 26 | const int flushEveryN_; 27 | 28 | int count_; 29 | std::unique_ptr mutex_; 30 | std::unique_ptr file_; 31 | }; -------------------------------------------------------------------------------- /WebServer/base/LogStream.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "LogStream.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | 12 | const char digits[] = "9876543210123456789"; 13 | const char* zero = digits + 9; 14 | 15 | // From muduo 16 | template 17 | size_t convert(char buf[], T value) 18 | { 19 | T i = value; 20 | char *p = buf; 21 | 22 | do 23 | { 24 | int lsd = static_cast(i % 10); 25 | i /= 10; 26 | *p++ = zero[lsd]; 27 | } while (i != 0); 28 | 29 | if (value < 0) 30 | { 31 | *p++ = '-'; 32 | } 33 | *p = '\0'; 34 | std::reverse(buf, p); 35 | 36 | return p - buf; 37 | } 38 | 39 | template class FixedBuffer; 40 | template class FixedBuffer; 41 | 42 | 43 | template 44 | void LogStream::formatInteger(T v) 45 | { 46 | // buffer容不下kMaxNumericSize个字符的话会被直接丢弃 47 | if (buffer_.avail() >= kMaxNumericSize) 48 | { 49 | size_t len = convert(buffer_.current(), v); 50 | buffer_.add(len); 51 | } 52 | } 53 | 54 | LogStream& LogStream::operator<<(short v) 55 | { 56 | *this << static_cast(v); 57 | return *this; 58 | } 59 | 60 | LogStream& LogStream::operator<<(unsigned short v) 61 | { 62 | *this << static_cast(v); 63 | return *this; 64 | } 65 | 66 | LogStream& LogStream::operator<<(int v) 67 | { 68 | formatInteger(v); 69 | return *this; 70 | } 71 | 72 | LogStream& LogStream::operator<<(unsigned int v) 73 | { 74 | formatInteger(v); 75 | return *this; 76 | } 77 | 78 | LogStream& LogStream::operator<<(long v) 79 | { 80 | formatInteger(v); 81 | return *this; 82 | } 83 | 84 | LogStream& LogStream::operator<<(unsigned long v) 85 | { 86 | formatInteger(v); 87 | return *this; 88 | } 89 | 90 | LogStream& LogStream::operator<<(long long v) 91 | { 92 | formatInteger(v); 93 | return *this; 94 | } 95 | 96 | LogStream& LogStream::operator<<(unsigned long long v) 97 | { 98 | formatInteger(v); 99 | return *this; 100 | } 101 | 102 | LogStream& LogStream::operator<<(double v) 103 | { 104 | if (buffer_.avail() >= kMaxNumericSize) 105 | { 106 | int len = snprintf(buffer_.current(), kMaxNumericSize, "%.12g", v); 107 | buffer_.add(len); 108 | } 109 | return *this; 110 | } 111 | 112 | LogStream& LogStream::operator<<(long double v) 113 | { 114 | if (buffer_.avail() >= kMaxNumericSize) 115 | { 116 | int len = snprintf(buffer_.current(), kMaxNumericSize, "%.12Lg", v); 117 | buffer_.add(len); 118 | } 119 | return *this; 120 | } -------------------------------------------------------------------------------- /WebServer/base/LogStream.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "noncopyable.h" 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | class AsyncLogging; 11 | const int kSmallBuffer = 4000; 12 | const int kLargeBuffer = 4000 * 1000; 13 | 14 | template 15 | class FixedBuffer: noncopyable 16 | { 17 | public: 18 | FixedBuffer() 19 | : cur_(data_) 20 | { } 21 | 22 | ~FixedBuffer() 23 | { } 24 | 25 | void append(const char* buf, size_t len) 26 | { 27 | if (avail() > static_cast(len)) 28 | { 29 | memcpy(cur_, buf, len); 30 | cur_ += len; 31 | } 32 | } 33 | 34 | const char* data() const { return data_; } 35 | int length() const { return static_cast(cur_ - data_); } 36 | 37 | char* current() { return cur_; } 38 | int avail() const { return static_cast(end() - cur_); } 39 | void add(size_t len) { cur_ += len; } 40 | 41 | void reset() { cur_ = data_; } 42 | void bzero() { memset(data_, 0, sizeof data_); } 43 | 44 | 45 | private: 46 | const char* end() const { return data_ + sizeof data_; } 47 | 48 | char data_[SIZE]; 49 | char* cur_; 50 | }; 51 | 52 | 53 | 54 | class LogStream : noncopyable 55 | { 56 | public: 57 | typedef FixedBuffer Buffer; 58 | 59 | LogStream& operator<<(bool v) 60 | { 61 | buffer_.append(v ? "1" : "0", 1); 62 | return *this; 63 | } 64 | 65 | LogStream& operator<<(short); 66 | LogStream& operator<<(unsigned short); 67 | LogStream& operator<<(int); 68 | LogStream& operator<<(unsigned int); 69 | LogStream& operator<<(long); 70 | LogStream& operator<<(unsigned long); 71 | LogStream& operator<<(long long); 72 | LogStream& operator<<(unsigned long long); 73 | 74 | LogStream& operator<<(const void*); 75 | 76 | LogStream& operator<<(float v) 77 | { 78 | *this << static_cast(v); 79 | return *this; 80 | } 81 | LogStream& operator<<(double); 82 | LogStream& operator<<(long double); 83 | 84 | LogStream& operator<<(char v) 85 | { 86 | buffer_.append(&v, 1); 87 | return *this; 88 | } 89 | 90 | LogStream& operator<<(const char* str) 91 | { 92 | if (str) 93 | buffer_.append(str, strlen(str)); 94 | else 95 | buffer_.append("(null)", 6); 96 | return *this; 97 | } 98 | 99 | LogStream& operator<<(const unsigned char* str) 100 | { 101 | return operator<<(reinterpret_cast(str)); 102 | } 103 | 104 | LogStream& operator<<(const std::string& v) 105 | { 106 | buffer_.append(v.c_str(), v.size()); 107 | return *this; 108 | } 109 | 110 | void append(const char* data, int len) { buffer_.append(data, len); } 111 | const Buffer& buffer() const { return buffer_; } 112 | void resetBuffer() { buffer_.reset(); } 113 | 114 | private: 115 | void staticCheck(); 116 | 117 | template 118 | void formatInteger(T); 119 | 120 | Buffer buffer_; 121 | 122 | static const int kMaxNumericSize = 32; 123 | }; -------------------------------------------------------------------------------- /WebServer/base/Logging.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Logging.h" 4 | #include "CurrentThread.h" 5 | #include "Thread.h" 6 | #include "AsyncLogging.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | static pthread_once_t once_control_ = PTHREAD_ONCE_INIT; 14 | static AsyncLogging *AsyncLogger_; 15 | 16 | std::string Logger::logFileName_ = "/linya_WebServer.log"; 17 | 18 | void once_init() 19 | { 20 | AsyncLogger_ = new AsyncLogging(Logger::getLogFileName()); 21 | AsyncLogger_->start(); 22 | } 23 | 24 | void output(const char* msg, int len) 25 | { 26 | pthread_once(&once_control_, once_init); 27 | AsyncLogger_->append(msg, len); 28 | } 29 | 30 | Logger::Impl::Impl(const char *fileName, int line) 31 | : stream_(), 32 | line_(line), 33 | basename_(fileName) 34 | { 35 | formatTime(); 36 | } 37 | 38 | void Logger::Impl::formatTime() 39 | { 40 | struct timeval tv; 41 | time_t time; 42 | char str_t[26] = {0}; 43 | gettimeofday (&tv, NULL); 44 | time = tv.tv_sec; 45 | struct tm* p_time = localtime(&time); 46 | strftime(str_t, 26, "%Y-%m-%d %H:%M:%S\n", p_time); 47 | stream_ << str_t; 48 | } 49 | 50 | Logger::Logger(const char *fileName, int line) 51 | : impl_(fileName, line) 52 | { } 53 | 54 | Logger::~Logger() 55 | { 56 | impl_.stream_ << " -- " << impl_.basename_ << ':' << impl_.line_ << '\n'; 57 | const LogStream::Buffer& buf(stream().buffer()); 58 | output(buf.data(), buf.length()); 59 | } -------------------------------------------------------------------------------- /WebServer/base/Logging.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "LogStream.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | class AsyncLogging; 11 | 12 | 13 | class Logger 14 | { 15 | public: 16 | Logger(const char *fileName, int line); 17 | ~Logger(); 18 | LogStream& stream() { return impl_.stream_; } 19 | 20 | static void setLogFileName(std::string fileName) 21 | { 22 | logFileName_ = fileName; 23 | } 24 | static std::string getLogFileName() 25 | { 26 | return logFileName_; 27 | } 28 | 29 | private: 30 | class Impl 31 | { 32 | public: 33 | Impl(const char *fileName, int line); 34 | void formatTime(); 35 | 36 | LogStream stream_; 37 | int line_; 38 | std::string basename_; 39 | }; 40 | Impl impl_; 41 | static std::string logFileName_; 42 | }; 43 | 44 | #define LOG Logger(__FILE__, __LINE__).stream() -------------------------------------------------------------------------------- /WebServer/base/Log的设计.txt: -------------------------------------------------------------------------------- 1 | Log的设计仿照了muduo库的设计,但我写的没那么复杂 2 | https://github.com/chenshuo/muduo 3 | 4 | 与Log相关的类包括FileUtil、LogFile、AsyncLogging、LogStream、Logging。 5 | 其中前4个类每一个类都含有一个append函数,Log的设计也是主要围绕这个append函数展开的。 6 | 7 | FileUtil是最底层的文件类,封装了Log文件的打开、写入并在类析构的时候关闭文件,底层使用了标准IO,该append函数直接向文件写。 8 | LogFile进一步封装了FileUtil,并设置了一个循环次数,没过这么多次就flush一次。 9 | AsyncLogging是核心,它负责启动一个log线程,专门用来将log写入LogFile,应用了“双缓冲技术”,其实有4个以上的缓冲区,但思想是一样的。 10 | AsyncLogging负责(定时到或被填满时)将缓冲区中的数据写入LogFile中。 11 | LogStream主要用来格式化输出,重载了<<运算符,同时也有自己的一块缓冲区,这里缓冲区的存在是为了缓存一行,把多个<<的结果连成一块。 12 | Logging是对外接口,Logging类内涵一个LogStream对象,主要是为了每次打log的时候在log之前和之后加上固定的格式化的信息,比如打log的行、 13 | 文件名等信息。 14 | -------------------------------------------------------------------------------- /WebServer/base/MutexLock.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "noncopyable.h" 5 | #include 6 | #include 7 | 8 | class MutexLock: noncopyable 9 | { 10 | public: 11 | MutexLock() 12 | { 13 | pthread_mutex_init(&mutex, NULL); 14 | } 15 | ~MutexLock() 16 | { 17 | pthread_mutex_lock(&mutex); 18 | pthread_mutex_destroy(&mutex); 19 | } 20 | void lock() 21 | { 22 | pthread_mutex_lock(&mutex); 23 | } 24 | void unlock() 25 | { 26 | pthread_mutex_unlock(&mutex); 27 | } 28 | pthread_mutex_t *get() 29 | { 30 | return &mutex; 31 | } 32 | private: 33 | pthread_mutex_t mutex; 34 | 35 | // 友元类不受访问权限影响 36 | private: 37 | friend class Condition; 38 | }; 39 | 40 | // 不手工调用lock()和unlock()函数,一切交给栈上的Guard对象的构造函数和析构函数负责 41 | // 封装加锁和解锁,作用域等于临界区域,加锁和解锁在同一个进程 42 | class MutexLockGuard: noncopyable 43 | { 44 | public: 45 | explicit MutexLockGuard(MutexLock &_mutex): 46 | mutex(_mutex) 47 | { 48 | mutex.lock(); 49 | } 50 | ~MutexLockGuard() 51 | { 52 | mutex.unlock(); 53 | } 54 | private: 55 | MutexLock &mutex; 56 | }; -------------------------------------------------------------------------------- /WebServer/base/Thread.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "Thread.h" 4 | #include "CurrentThread.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | using namespace std; 17 | 18 | 19 | namespace CurrentThread 20 | { 21 | __thread int t_cachedTid = 0; 22 | __thread char t_tidString[32]; 23 | __thread int t_tidStringLength = 6; 24 | __thread const char* t_threadName = "default"; 25 | } 26 | 27 | 28 | pid_t gettid() 29 | { 30 | return static_cast(::syscall(SYS_gettid)); 31 | } 32 | 33 | void CurrentThread::cacheTid() 34 | { 35 | if (t_cachedTid == 0) 36 | { 37 | t_cachedTid = gettid(); 38 | t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid); 39 | } 40 | } 41 | 42 | // 为了在线程中保留name,tid这些数据 43 | // 线程函数参数结构体 44 | struct ThreadData 45 | { 46 | typedef Thread::ThreadFunc ThreadFunc; 47 | ThreadFunc func_; // 实际线程要运行的函数 48 | string name_; // 线程名 49 | pid_t* tid_; 50 | CountDownLatch* latch_; 51 | 52 | ThreadData(const ThreadFunc &func, const string& name, pid_t *tid, CountDownLatch *latch) 53 | : func_(func), 54 | name_(name), 55 | tid_(tid), 56 | latch_(latch) 57 | { } 58 | 59 | void runInThread() 60 | { 61 | *tid_ = CurrentThread::tid(); 62 | tid_ = NULL; 63 | latch_->countDown(); 64 | latch_ = NULL; 65 | 66 | CurrentThread::t_threadName = name_.empty() ? "Thread" : name_.c_str(); 67 | prctl(PR_SET_NAME, CurrentThread::t_threadName); 68 | 69 | func_(); 70 | CurrentThread::t_threadName = "finished"; 71 | } 72 | }; 73 | 74 | void *startThread(void* obj) 75 | { 76 | ThreadData* data = static_cast(obj); 77 | data->runInThread(); 78 | delete data; 79 | return NULL; 80 | } 81 | 82 | 83 | Thread::Thread(const ThreadFunc &func, const string &n) 84 | : started_(false), 85 | joined_(false), 86 | pthreadId_(0), 87 | tid_(0), 88 | func_(func), 89 | name_(n), 90 | latch_(1) 91 | { 92 | setDefaultName(); 93 | } 94 | 95 | Thread::~Thread() 96 | { 97 | if (started_ && !joined_) 98 | pthread_detach(pthreadId_); 99 | } 100 | 101 | void Thread::setDefaultName() 102 | { 103 | if (name_.empty()) 104 | { 105 | char buf[32]; 106 | snprintf(buf, sizeof buf, "Thread"); 107 | name_ = buf; 108 | } 109 | } 110 | 111 | // 创建线程 112 | void Thread::start() 113 | { 114 | assert(!started_); 115 | started_ = true; 116 | ThreadData* data = new ThreadData(func_, name_, &tid_, &latch_); 117 | if (pthread_create(&pthreadId_, NULL, &startThread, data)) 118 | { 119 | started_ = false; 120 | delete data; 121 | } 122 | else 123 | { 124 | latch_.wait(); 125 | assert(tid_ > 0); 126 | } 127 | } 128 | 129 | int Thread::join() 130 | { 131 | assert(started_); 132 | assert(!joined_); 133 | joined_ = true; 134 | return pthread_join(pthreadId_, NULL); 135 | } -------------------------------------------------------------------------------- /WebServer/base/Thread.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | #include "CountDownLatch.h" 5 | #include "noncopyable.h" 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* 线程类 */ 14 | 15 | class Thread : noncopyable 16 | { 17 | public: 18 | typedef std::function ThreadFunc; 19 | explicit Thread(const ThreadFunc&, const std::string& name = std::string()); 20 | ~Thread(); 21 | void start(); 22 | int join(); 23 | bool started() const { return started_; } 24 | pid_t tid() const { return tid_; } 25 | const std::string& name() const { return name_; } 26 | 27 | private: 28 | void setDefaultName(); 29 | bool started_; 30 | bool joined_; 31 | pthread_t pthreadId_; 32 | pid_t tid_; 33 | ThreadFunc func_; 34 | std::string name_; 35 | CountDownLatch latch_; 36 | }; -------------------------------------------------------------------------------- /WebServer/base/noncopyable.h: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #pragma once 4 | 5 | class noncopyable 6 | { 7 | protected: 8 | noncopyable() {} 9 | ~noncopyable() {} 10 | private: 11 | noncopyable(const noncopyable&); 12 | const noncopyable& operator=(const noncopyable&); 13 | }; -------------------------------------------------------------------------------- /WebServer/base/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(LoggingTest LoggingTest.cpp) 2 | target_link_libraries(LoggingTest libserver_base) -------------------------------------------------------------------------------- /WebServer/base/tests/LoggingTest.cpp: -------------------------------------------------------------------------------- 1 | // @Author Lin Ya 2 | // @Email xxbbb@vip.qq.com 3 | #include "../Logging.h" 4 | #include "../Thread.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | using namespace std; 11 | 12 | void threadFunc() 13 | { 14 | for (int i = 0; i < 100000; ++i) 15 | { 16 | LOG << i; 17 | } 18 | } 19 | 20 | void type_test() 21 | { 22 | // 13 lines 23 | cout << "----------type test-----------" << endl; 24 | LOG << 0; 25 | LOG << 1234567890123; 26 | LOG << 1.0f; 27 | LOG << 3.1415926; 28 | LOG << (short) 1; 29 | LOG << (long long) 1; 30 | LOG << (unsigned int) 1; 31 | LOG << (unsigned long) 1; 32 | LOG << (long double) 1.6555556; 33 | LOG << (unsigned long long) 1; 34 | LOG << 'c'; 35 | LOG << "abcdefg"; 36 | LOG << string("This is a string"); 37 | } 38 | 39 | void stressing_single_thread() 40 | { 41 | // 100000 lines 42 | cout << "----------stressing test single thread-----------" << endl; 43 | for (int i = 0; i < 100000; ++i) 44 | { 45 | LOG << i; 46 | } 47 | } 48 | 49 | void stressing_multi_threads(int threadNum = 4) 50 | { 51 | // threadNum * 100000 lines 52 | cout << "----------stressing test multi thread-----------" << endl; 53 | vector> vsp; 54 | for (int i = 0; i < threadNum; ++i) 55 | { 56 | shared_ptr tmp(new Thread(threadFunc, "testFunc")); 57 | vsp.push_back(tmp); 58 | } 59 | for (int i = 0; i < threadNum; ++i) 60 | { 61 | vsp[i]->start(); 62 | } 63 | sleep(3); 64 | } 65 | 66 | void other() 67 | { 68 | // 1 line 69 | cout << "----------other test-----------" << endl; 70 | LOG << "fddsa" << 'c' << 0 << 3.666 << string("This is a string"); 71 | } 72 | 73 | 74 | int main() 75 | { 76 | // 共500014行 77 | type_test(); 78 | sleep(3); 79 | 80 | stressing_single_thread(); 81 | sleep(3); 82 | 83 | other(); 84 | sleep(3); 85 | 86 | stressing_multi_threads(); 87 | sleep(3); 88 | return 0; 89 | } -------------------------------------------------------------------------------- /WebServer/config.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | -------------------------------------------------------------------------------- /WebServer/tests/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable(HTTPClient HTTPClient.cpp) -------------------------------------------------------------------------------- /WebServer/tests/HTTPClient.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | using namespace std; 15 | 16 | #define MAXSIZE 1024 17 | #define IPADDRESS "127.0.0.1" 18 | #define SERV_PORT 8888 19 | #define FDSIZE 1024 20 | #define EPOLLEVENTS 20 21 | 22 | //static void handle_connection(int sockfd); 23 | //static void handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf); 24 | // static void do_read(int epollfd,int fd,int sockfd,char *buf); 25 | // static void do_read(int epollfd,int fd,int sockfd,char *buf); 26 | // static void do_write(int epollfd,int fd,int sockfd,char *buf); 27 | // static void add_event(int epollfd,int fd,int state); 28 | // static void delete_event(int epollfd,int fd,int state); 29 | // static void modify_event(int epollfd,int fd,int state); 30 | 31 | int setSocketNonBlocking1(int fd) 32 | { 33 | int flag = fcntl(fd, F_GETFL, 0); 34 | if(flag == -1) 35 | return -1; 36 | 37 | flag |= O_NONBLOCK; 38 | if(fcntl(fd, F_SETFL, flag) == -1) 39 | return -1; 40 | return 0; 41 | } 42 | int main(int argc,char *argv[]) 43 | { 44 | int sockfd; 45 | struct sockaddr_in servaddr; 46 | sockfd = socket(AF_INET,SOCK_STREAM,0); 47 | bzero(&servaddr,sizeof(servaddr)); 48 | servaddr.sin_family = AF_INET; 49 | servaddr.sin_port = htons(SERV_PORT); 50 | inet_pton(AF_INET,IPADDRESS,&servaddr.sin_addr); 51 | char buff[4096]; 52 | buff[0] = '\0'; 53 | // 发空串 54 | const char *p = " "; 55 | if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == 0 ) 56 | { 57 | setSocketNonBlocking1(sockfd); 58 | cout << "1:" << endl; 59 | ssize_t n = write(sockfd, p, strlen(p)); 60 | cout << "strlen(p) = " << strlen(p) << endl; 61 | sleep(1); 62 | n = read(sockfd, buff, 4096); 63 | cout << "n=" << n << endl; 64 | printf("%s", buff); 65 | close(sockfd); 66 | } 67 | else{ 68 | perror("err1"); 69 | } 70 | sleep(1); 71 | 72 | // 发"GET HTTP/1.1" 73 | p = "GET HTTP/1.1"; 74 | sockfd = socket(AF_INET,SOCK_STREAM,0); 75 | if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == 0) 76 | { 77 | setSocketNonBlocking1(sockfd); 78 | cout << "2:" << endl; 79 | ssize_t n = write(sockfd, p, strlen(p)); 80 | cout << "strlen(p) = " << strlen(p) << endl; 81 | sleep(1); 82 | n = read(sockfd, buff, 4096); 83 | cout << "n=" << n << endl; 84 | printf("%s", buff); 85 | close(sockfd); 86 | } 87 | else 88 | { 89 | perror("err2"); 90 | } 91 | sleep(1); 92 | 93 | // 发 94 | // GET HTTP/1.1 95 | // Host: 192.168.52.135:8888 96 | // Content-Type: application/x-www-form-urlencoded 97 | // Connection: Keep-Alive 98 | 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"; 99 | sockfd = socket(AF_INET,SOCK_STREAM,0); 100 | if (connect(sockfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == 0) 101 | { 102 | setSocketNonBlocking1(sockfd); 103 | cout << "3:" << endl; 104 | ssize_t n = write(sockfd, p, strlen(p)); 105 | cout << "strlen(p) = " << strlen(p) << endl; 106 | sleep(1); 107 | n = read(sockfd, buff, 4096); 108 | cout << "n=" << n << endl; 109 | printf("%s", buff); 110 | close(sockfd); 111 | } 112 | else 113 | { 114 | perror("err3"); 115 | } 116 | return 0; 117 | } 118 | 119 | 120 | // static void handle_connection(int sockfd) 121 | // { 122 | // int epollfd; 123 | // struct epoll_event events[EPOLLEVENTS]; 124 | // char buf[MAXSIZE]; 125 | // int ret; 126 | // epollfd = epoll_create(FDSIZE); 127 | // add_event(epollfd,STDIN_FILENO,EPOLLIN); 128 | // for ( ; ; ) 129 | // { 130 | // ret = epoll_wait(epollfd,events,EPOLLEVENTS,-1); 131 | // handle_events(epollfd,events,ret,sockfd,buf); 132 | // } 133 | // close(epollfd); 134 | // } 135 | 136 | // static void 137 | // handle_events(int epollfd,struct epoll_event *events,int num,int sockfd,char *buf) 138 | // { 139 | // int fd; 140 | // int i; 141 | // for (i = 0;i < num;i++) 142 | // { 143 | // fd = events[i].data.fd; 144 | // if (events[i].events & EPOLLIN) 145 | // do_read(epollfd,fd,sockfd,buf); 146 | // else if (events[i].events & EPOLLOUT) 147 | // do_write(epollfd,fd,sockfd,buf); 148 | // } 149 | // } 150 | 151 | // static void do_read(int epollfd,int fd,int sockfd,char *buf) 152 | // { 153 | // int nread; 154 | // nread = read(fd,buf,MAXSIZE); 155 | // if (nread == -1) 156 | // { 157 | // perror("read error:"); 158 | // close(fd); 159 | // } 160 | // else if (nread == 0) 161 | // { 162 | // fprintf(stderr,"server close.\n"); 163 | // close(fd); 164 | // } 165 | // else 166 | // { 167 | // if (fd == STDIN_FILENO) 168 | // add_event(epollfd,sockfd,EPOLLOUT); 169 | // else 170 | // { 171 | // delete_event(epollfd,sockfd,EPOLLIN); 172 | // add_event(epollfd,STDOUT_FILENO,EPOLLOUT); 173 | // } 174 | // } 175 | // } 176 | 177 | // static void do_write(int epollfd,int fd,int sockfd,char *buf) 178 | // { 179 | // int nwrite; 180 | // nwrite = write(fd,buf,strlen(buf)); 181 | // if (nwrite == -1) 182 | // { 183 | // perror("write error:"); 184 | // close(fd); 185 | // } 186 | // else 187 | // { 188 | // if (fd == STDOUT_FILENO) 189 | // delete_event(epollfd,fd,EPOLLOUT); 190 | // else 191 | // modify_event(epollfd,fd,EPOLLIN); 192 | // } 193 | // memset(buf,0,MAXSIZE); 194 | // } 195 | 196 | // static void add_event(int epollfd,int fd,int state) 197 | // { 198 | // struct epoll_event ev; 199 | // ev.events = state; 200 | // ev.data.fd = fd; 201 | // epoll_ctl(epollfd,EPOLL_CTL_ADD,fd,&ev); 202 | // } 203 | 204 | // static void delete_event(int epollfd,int fd,int state) 205 | // { 206 | // struct epoll_event ev; 207 | // ev.events = state; 208 | // ev.data.fd = fd; 209 | // epoll_ctl(epollfd,EPOLL_CTL_DEL,fd,&ev); 210 | // } 211 | 212 | // static void modify_event(int epollfd,int fd,int state) 213 | // { 214 | // struct epoll_event ev; 215 | // ev.events = state; 216 | // ev.data.fd = fd; 217 | // epoll_ctl(epollfd,EPOLL_CTL_MOD,fd,&ev); 218 | // } -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeCache.txt: -------------------------------------------------------------------------------- 1 | # This is the CMakeCache file. 2 | # For build in directory: /home/linya/beifen/myserver/tests/build/release 3 | # It was generated by CMake: /usr/bin/cmake 4 | # You can edit this file to change values found and used by cmake. 5 | # If you do not want to change any of the values, simply exit the editor. 6 | # If you do want to change a value, simply edit, save, and exit the editor. 7 | # The syntax for the file is as follows: 8 | # KEY:TYPE=VALUE 9 | # KEY is the name of a variable in the cache. 10 | # TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. 11 | # VALUE is the current value for the KEY. 12 | 13 | ######################## 14 | # EXTERNAL cache entries 15 | ######################## 16 | 17 | //Path to a library. 18 | BOOSTPO_LIBRARY:FILEPATH=BOOSTPO_LIBRARY-NOTFOUND 19 | 20 | //Path to a library. 21 | BOOSTTEST_LIBRARY:FILEPATH=BOOSTTEST_LIBRARY-NOTFOUND 22 | 23 | //The directory containing a CMake configuration file for Boost. 24 | Boost_DIR:PATH=Boost_DIR-NOTFOUND 25 | 26 | //Path to a file. 27 | Boost_INCLUDE_DIR:PATH=Boost_INCLUDE_DIR-NOTFOUND 28 | 29 | //Path to a file. 30 | CARES_INCLUDE_DIR:PATH=CARES_INCLUDE_DIR-NOTFOUND 31 | 32 | //Path to a library. 33 | CARES_LIBRARY:FILEPATH=CARES_LIBRARY-NOTFOUND 34 | 35 | //Path to a program. 36 | CMAKE_AR:FILEPATH=/usr/bin/ar 37 | 38 | //No help, variable specified on the command line. 39 | CMAKE_BUILD_NO_EXAMPLES:UNINITIALIZED=0 40 | 41 | //Choose the type of build, options are: None(CMAKE_CXX_FLAGS or 42 | // CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. 43 | CMAKE_BUILD_TYPE:STRING=release 44 | 45 | //Enable/Disable color output during build. 46 | CMAKE_COLOR_MAKEFILE:BOOL=ON 47 | 48 | //CXX compiler. 49 | CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ 50 | 51 | //Flags used by the compiler during all build types. 52 | CMAKE_CXX_FLAGS:STRING= 53 | 54 | //Flags used by the compiler during debug builds. 55 | CMAKE_CXX_FLAGS_DEBUG:STRING=-g 56 | 57 | //Flags used by the compiler during release minsize builds. 58 | CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG 59 | 60 | //Flags used by the compiler during release builds (/MD /Ob1 /Oi 61 | // /Ot /Oy /Gs will produce slightly less optimized but smaller 62 | // files). 63 | CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG 64 | 65 | //Flags used by the compiler during Release with Debug Info builds. 66 | CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG 67 | 68 | //C compiler. 69 | CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc 70 | 71 | //Flags used by the compiler during all build types. 72 | CMAKE_C_FLAGS:STRING= 73 | 74 | //Flags used by the compiler during debug builds. 75 | CMAKE_C_FLAGS_DEBUG:STRING=-g 76 | 77 | //Flags used by the compiler during release minsize builds. 78 | CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG 79 | 80 | //Flags used by the compiler during release builds (/MD /Ob1 /Oi 81 | // /Ot /Oy /Gs will produce slightly less optimized but smaller 82 | // files). 83 | CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG 84 | 85 | //Flags used by the compiler during Release with Debug Info builds. 86 | CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG 87 | 88 | //Flags used by the linker. 89 | CMAKE_EXE_LINKER_FLAGS:STRING=' ' 90 | 91 | //Flags used by the linker during debug builds. 92 | CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= 93 | 94 | //Flags used by the linker during release minsize builds. 95 | CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= 96 | 97 | //Flags used by the linker during release builds. 98 | CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= 99 | 100 | //Flags used by the linker during Release with Debug Info builds. 101 | CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= 102 | 103 | //Enable/Disable output of compile commands during generation. 104 | CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF 105 | 106 | //Install path prefix, prepended onto install directories. 107 | CMAKE_INSTALL_PREFIX:PATH=/home/linya/beifen/myserver/tests/build/release-install 108 | 109 | //Path to a program. 110 | CMAKE_LINKER:FILEPATH=/usr/bin/ld 111 | 112 | //Path to a program. 113 | CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make 114 | 115 | //Flags used by the linker during the creation of modules. 116 | CMAKE_MODULE_LINKER_FLAGS:STRING=' ' 117 | 118 | //Flags used by the linker during debug builds. 119 | CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= 120 | 121 | //Flags used by the linker during release minsize builds. 122 | CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= 123 | 124 | //Flags used by the linker during release builds. 125 | CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= 126 | 127 | //Flags used by the linker during Release with Debug Info builds. 128 | CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= 129 | 130 | //Path to a program. 131 | CMAKE_NM:FILEPATH=/usr/bin/nm 132 | 133 | //Path to a program. 134 | CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy 135 | 136 | //Path to a program. 137 | CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump 138 | 139 | //Value Computed by CMake 140 | CMAKE_PROJECT_NAME:STATIC=muduo 141 | 142 | //Path to a program. 143 | CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib 144 | 145 | //Flags used by the linker during the creation of dll's. 146 | CMAKE_SHARED_LINKER_FLAGS:STRING=' ' 147 | 148 | //Flags used by the linker during debug builds. 149 | CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= 150 | 151 | //Flags used by the linker during release minsize builds. 152 | CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= 153 | 154 | //Flags used by the linker during release builds. 155 | CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= 156 | 157 | //Flags used by the linker during Release with Debug Info builds. 158 | CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= 159 | 160 | //If set, runtime paths are not added when installing shared libraries, 161 | // but are added when building. 162 | CMAKE_SKIP_INSTALL_RPATH:BOOL=NO 163 | 164 | //If set, runtime paths are not added when using shared libraries. 165 | CMAKE_SKIP_RPATH:BOOL=NO 166 | 167 | //Flags used by the linker during the creation of static libraries. 168 | CMAKE_STATIC_LINKER_FLAGS:STRING= 169 | 170 | //Flags used by the linker during debug builds. 171 | CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= 172 | 173 | //Flags used by the linker during release minsize builds. 174 | CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= 175 | 176 | //Flags used by the linker during release builds. 177 | CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= 178 | 179 | //Flags used by the linker during Release with Debug Info builds. 180 | CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= 181 | 182 | //Path to a program. 183 | CMAKE_STRIP:FILEPATH=/usr/bin/strip 184 | 185 | //If true, cmake will use relative paths in makefiles and projects. 186 | CMAKE_USE_RELATIVE_PATHS:BOOL=OFF 187 | 188 | //If this value is on, makefiles will be generated without the 189 | // .SILENT directive, and all commands will be echoed to the console 190 | // during the make. This is useful for debugging only. With Visual 191 | // Studio IDE projects all commands are done without /nologo. 192 | CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE 193 | 194 | //Path to a file. 195 | CURL_INCLUDE_DIR:PATH=CURL_INCLUDE_DIR-NOTFOUND 196 | 197 | //Path to a library. 198 | CURL_LIBRARY:FILEPATH=CURL_LIBRARY-NOTFOUND 199 | 200 | //Path to a file. 201 | GD_INCLUDE_DIR:PATH=GD_INCLUDE_DIR-NOTFOUND 202 | 203 | //Path to a library. 204 | GD_LIBRARY:FILEPATH=GD_LIBRARY-NOTFOUND 205 | 206 | //Path to a file. 207 | HIREDIS_INCLUDE_DIR:PATH=HIREDIS_INCLUDE_DIR-NOTFOUND 208 | 209 | //Path to a library. 210 | HIREDIS_LIBRARY:FILEPATH=HIREDIS_LIBRARY-NOTFOUND 211 | 212 | //Path to a file. 213 | MHD_INCLUDE_DIR:PATH=MHD_INCLUDE_DIR-NOTFOUND 214 | 215 | //Path to a library. 216 | MHD_LIBRARY:FILEPATH=MHD_LIBRARY-NOTFOUND 217 | 218 | //Path to a file. 219 | PROTOBUF_INCLUDE_DIR:PATH=PROTOBUF_INCLUDE_DIR-NOTFOUND 220 | 221 | //Path to a library. 222 | PROTOBUF_LIBRARY:FILEPATH=PROTOBUF_LIBRARY-NOTFOUND 223 | 224 | //Path to a library. 225 | PROTOBUF_LIBRARY_DEBUG:FILEPATH=PROTOBUF_LIBRARY_DEBUG-NOTFOUND 226 | 227 | //Path to a library. 228 | PROTOBUF_LITE_LIBRARY:FILEPATH=PROTOBUF_LITE_LIBRARY-NOTFOUND 229 | 230 | //Path to a library. 231 | PROTOBUF_LITE_LIBRARY_DEBUG:FILEPATH=PROTOBUF_LITE_LIBRARY_DEBUG-NOTFOUND 232 | 233 | //The Google Protocol Buffers Compiler 234 | PROTOBUF_PROTOC_EXECUTABLE:FILEPATH=PROTOBUF_PROTOC_EXECUTABLE-NOTFOUND 235 | 236 | //Path to a library. 237 | PROTOBUF_PROTOC_LIBRARY:FILEPATH=PROTOBUF_PROTOC_LIBRARY-NOTFOUND 238 | 239 | //Path to a library. 240 | PROTOBUF_PROTOC_LIBRARY_DEBUG:FILEPATH=PROTOBUF_PROTOC_LIBRARY_DEBUG-NOTFOUND 241 | 242 | //Path to a file. 243 | TCMALLOC_INCLUDE_DIR:PATH=TCMALLOC_INCLUDE_DIR-NOTFOUND 244 | 245 | //Path to a library. 246 | TCMALLOC_LIBRARY:FILEPATH=TCMALLOC_LIBRARY-NOTFOUND 247 | 248 | //Path to a program. 249 | THRIFT_COMPILER:FILEPATH=THRIFT_COMPILER-NOTFOUND 250 | 251 | //Path to a file. 252 | THRIFT_INCLUDE_DIR:PATH=THRIFT_INCLUDE_DIR-NOTFOUND 253 | 254 | //Path to a library. 255 | THRIFT_LIBRARY:FILEPATH=THRIFT_LIBRARY-NOTFOUND 256 | 257 | //Path to a file. 258 | ZLIB_INCLUDE_DIR:PATH=ZLIB_INCLUDE_DIR-NOTFOUND 259 | 260 | //Path to a library. 261 | ZLIB_LIBRARY:FILEPATH=ZLIB_LIBRARY-NOTFOUND 262 | 263 | //Dependencies for the target 264 | ace_logging_proto_LIB_DEPENDS:STATIC=general;protobuf;general;pthread; 265 | 266 | //Dependencies for the target 267 | echo_proto_LIB_DEPENDS:STATIC=general;protobuf;general;pthread; 268 | 269 | //Value Computed by CMake 270 | muduo_BINARY_DIR:STATIC=/home/linya/beifen/myserver/tests/build/release 271 | 272 | //Value Computed by CMake 273 | muduo_SOURCE_DIR:STATIC=/home/linya/beifen/myserver/tests/muduo 274 | 275 | //Dependencies for the target 276 | muduo_base_LIB_DEPENDS:STATIC=general;pthread;general;rt; 277 | 278 | //Dependencies for the target 279 | muduo_base_cpp11_LIB_DEPENDS:STATIC=general;pthread;general;rt; 280 | 281 | //Dependencies for the target 282 | muduo_cdns_LIB_DEPENDS:STATIC=general;muduo_net;general;cares; 283 | 284 | //Dependencies for the target 285 | muduo_curl_LIB_DEPENDS:STATIC=general;muduo_net;general;curl; 286 | 287 | //Dependencies for the target 288 | muduo_http_LIB_DEPENDS:STATIC=general;muduo_net; 289 | 290 | //Dependencies for the target 291 | muduo_inspect_LIB_DEPENDS:STATIC=general;muduo_http; 292 | 293 | //Dependencies for the target 294 | muduo_net_LIB_DEPENDS:STATIC=general;muduo_base; 295 | 296 | //Dependencies for the target 297 | muduo_net_cpp11_LIB_DEPENDS:STATIC=general;muduo_base_cpp11; 298 | 299 | //Dependencies for the target 300 | muduo_protobuf_codec_LIB_DEPENDS:STATIC=general;muduo_net;general;protobuf;general;z; 301 | 302 | //Dependencies for the target 303 | muduo_protobuf_codec_cpp11_LIB_DEPENDS:STATIC=general;muduo_net_cpp11;general;protobuf;general;z; 304 | 305 | //Dependencies for the target 306 | muduo_protorpc_LIB_DEPENDS:STATIC=general;muduo_protorpc_wire;general;muduo_protobuf_codec;general;muduo_net;general;protobuf;general;z; 307 | 308 | //Dependencies for target 309 | muduo_protorpc_wire_LIB_DEPENDS:STATIC= 310 | 311 | //Dependencies for target 312 | muduo_protorpc_wire_cpp11_LIB_DEPENDS:STATIC= 313 | 314 | //Dependencies for the target 315 | muduo_pubsub_LIB_DEPENDS:STATIC=general;muduo_net; 316 | 317 | //Dependencies for the target 318 | muduo_thrift_LIB_DEPENDS:STATIC=general;muduo_net;general;thrift; 319 | 320 | //Dependencies for the target 321 | protobuf_codec_LIB_DEPENDS:STATIC=general;protobuf;general;muduo_net;general;z; 322 | 323 | //Dependencies for the target 324 | query_proto_LIB_DEPENDS:STATIC=general;protobuf;general;pthread; 325 | 326 | //Dependencies for the target 327 | resolver_proto_LIB_DEPENDS:STATIC=general;protobuf;general;pthread; 328 | 329 | //Dependencies for the target 330 | sudoku_proto_LIB_DEPENDS:STATIC=general;protobuf;general;pthread; 331 | 332 | 333 | ######################## 334 | # INTERNAL cache entries 335 | ######################## 336 | 337 | //ADVANCED property for variable: Boost_DIR 338 | Boost_DIR-ADVANCED:INTERNAL=1 339 | //ADVANCED property for variable: Boost_INCLUDE_DIR 340 | Boost_INCLUDE_DIR-ADVANCED:INTERNAL=1 341 | //ADVANCED property for variable: CMAKE_AR 342 | CMAKE_AR-ADVANCED:INTERNAL=1 343 | //ADVANCED property for variable: CMAKE_BUILD_TOOL 344 | CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 345 | //What is the target build tool cmake is generating for. 346 | CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make 347 | //This is the directory where this CMakeCache.txt was created 348 | CMAKE_CACHEFILE_DIR:INTERNAL=/home/linya/beifen/myserver/tests/build/release 349 | //Major version of cmake used to create the current loaded cache 350 | CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 351 | //Minor version of cmake used to create the current loaded cache 352 | CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 353 | //Patch version of cmake used to create the current loaded cache 354 | CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 355 | //ADVANCED property for variable: CMAKE_COLOR_MAKEFILE 356 | CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 357 | //Path to CMake executable. 358 | CMAKE_COMMAND:INTERNAL=/usr/bin/cmake 359 | //Path to cpack program executable. 360 | CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack 361 | //Path to ctest program executable. 362 | CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest 363 | //ADVANCED property for variable: CMAKE_CXX_COMPILER 364 | CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 365 | //ADVANCED property for variable: CMAKE_CXX_FLAGS 366 | CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 367 | //ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG 368 | CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 369 | //ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL 370 | CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 371 | //ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE 372 | CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 373 | //ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO 374 | CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 375 | //ADVANCED property for variable: CMAKE_C_COMPILER 376 | CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 377 | //ADVANCED property for variable: CMAKE_C_FLAGS 378 | CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 379 | //ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG 380 | CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 381 | //ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL 382 | CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 383 | //ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE 384 | CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 385 | //ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO 386 | CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 387 | //Executable file format 388 | CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF 389 | //ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS 390 | CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 391 | //ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG 392 | CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 393 | //ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL 394 | CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 395 | //ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE 396 | CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 397 | //ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO 398 | CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 399 | //ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS 400 | CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 401 | //Name of generator. 402 | CMAKE_GENERATOR:INTERNAL=Unix Makefiles 403 | //Name of generator toolset. 404 | CMAKE_GENERATOR_TOOLSET:INTERNAL= 405 | //Have symbol pthread_create 406 | CMAKE_HAVE_LIBC_CREATE:INTERNAL= 407 | //Have library pthreads 408 | CMAKE_HAVE_PTHREADS_CREATE:INTERNAL= 409 | //Have library pthread 410 | CMAKE_HAVE_PTHREAD_CREATE:INTERNAL=1 411 | //Have include pthread.h 412 | CMAKE_HAVE_PTHREAD_H:INTERNAL=1 413 | //Start directory with the top level CMakeLists.txt file for this 414 | // project 415 | CMAKE_HOME_DIRECTORY:INTERNAL=/home/linya/beifen/myserver/tests/muduo 416 | //Install .so files without execute permission. 417 | CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 418 | //ADVANCED property for variable: CMAKE_LINKER 419 | CMAKE_LINKER-ADVANCED:INTERNAL=1 420 | //ADVANCED property for variable: CMAKE_MAKE_PROGRAM 421 | CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 422 | //ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS 423 | CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 424 | //ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG 425 | CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 426 | //ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL 427 | CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 428 | //ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE 429 | CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 430 | //ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO 431 | CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 432 | //ADVANCED property for variable: CMAKE_NM 433 | CMAKE_NM-ADVANCED:INTERNAL=1 434 | //number of local generators 435 | CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=46 436 | //ADVANCED property for variable: CMAKE_OBJCOPY 437 | CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 438 | //ADVANCED property for variable: CMAKE_OBJDUMP 439 | CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 440 | //ADVANCED property for variable: CMAKE_RANLIB 441 | CMAKE_RANLIB-ADVANCED:INTERNAL=1 442 | //Path to CMake installation. 443 | CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8 444 | //ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS 445 | CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 446 | //ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG 447 | CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 448 | //ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL 449 | CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 450 | //ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE 451 | CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 452 | //ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO 453 | CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 454 | //ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH 455 | CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 456 | //ADVANCED property for variable: CMAKE_SKIP_RPATH 457 | CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 458 | //ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS 459 | CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 460 | //ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG 461 | CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 462 | //ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL 463 | CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 464 | //ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE 465 | CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 466 | //ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO 467 | CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 468 | //ADVANCED property for variable: CMAKE_STRIP 469 | CMAKE_STRIP-ADVANCED:INTERNAL=1 470 | //uname command 471 | CMAKE_UNAME:INTERNAL=/bin/uname 472 | //ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS 473 | CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 474 | //ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE 475 | CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 476 | //ADVANCED property for variable: CURL_INCLUDE_DIR 477 | CURL_INCLUDE_DIR-ADVANCED:INTERNAL=1 478 | //ADVANCED property for variable: CURL_LIBRARY 479 | CURL_LIBRARY-ADVANCED:INTERNAL=1 480 | //Details about finding Threads 481 | FIND_PACKAGE_MESSAGE_DETAILS_Threads:INTERNAL=[TRUE][v()] 482 | //Have function accept4 483 | HAVE_ACCEPT4:INTERNAL=1 484 | //ADVANCED property for variable: PROTOBUF_INCLUDE_DIR 485 | PROTOBUF_INCLUDE_DIR-ADVANCED:INTERNAL=1 486 | //ADVANCED property for variable: PROTOBUF_LIBRARY 487 | PROTOBUF_LIBRARY-ADVANCED:INTERNAL=1 488 | //ADVANCED property for variable: PROTOBUF_LIBRARY_DEBUG 489 | PROTOBUF_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 490 | //ADVANCED property for variable: PROTOBUF_LITE_LIBRARY 491 | PROTOBUF_LITE_LIBRARY-ADVANCED:INTERNAL=1 492 | //ADVANCED property for variable: PROTOBUF_LITE_LIBRARY_DEBUG 493 | PROTOBUF_LITE_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 494 | //ADVANCED property for variable: PROTOBUF_PROTOC_EXECUTABLE 495 | PROTOBUF_PROTOC_EXECUTABLE-ADVANCED:INTERNAL=1 496 | //ADVANCED property for variable: PROTOBUF_PROTOC_LIBRARY 497 | PROTOBUF_PROTOC_LIBRARY-ADVANCED:INTERNAL=1 498 | //ADVANCED property for variable: PROTOBUF_PROTOC_LIBRARY_DEBUG 499 | PROTOBUF_PROTOC_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 500 | //ADVANCED property for variable: ZLIB_INCLUDE_DIR 501 | ZLIB_INCLUDE_DIR-ADVANCED:INTERNAL=1 502 | //ADVANCED property for variable: ZLIB_LIBRARY 503 | ZLIB_LIBRARY-ADVANCED:INTERNAL=1 504 | //Components requested for this build tree. 505 | _Boost_COMPONENTS_SEARCHED:INTERNAL= 506 | //Last used Boost_INCLUDE_DIR value. 507 | _Boost_INCLUDE_DIR_LAST:INTERNAL=Boost_INCLUDE_DIR-NOTFOUND 508 | //Last used Boost_USE_MULTITHREADED value. 509 | _Boost_USE_MULTITHREADED_LAST:INTERNAL=TRUE 510 | 511 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "GNU") 4 | set(CMAKE_C_COMPILER_VERSION "4.8.4") 5 | set(CMAKE_C_PLATFORM_ID "Linux") 6 | 7 | set(CMAKE_AR "/usr/bin/ar") 8 | set(CMAKE_RANLIB "/usr/bin/ranlib") 9 | set(CMAKE_LINKER "/usr/bin/ld") 10 | set(CMAKE_COMPILER_IS_GNUCC 1) 11 | set(CMAKE_C_COMPILER_LOADED 1) 12 | set(CMAKE_C_COMPILER_WORKS TRUE) 13 | set(CMAKE_C_ABI_COMPILED TRUE) 14 | set(CMAKE_COMPILER_IS_MINGW ) 15 | set(CMAKE_COMPILER_IS_CYGWIN ) 16 | if(CMAKE_COMPILER_IS_CYGWIN) 17 | set(CYGWIN 1) 18 | set(UNIX 1) 19 | endif() 20 | 21 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 22 | 23 | if(CMAKE_COMPILER_IS_MINGW) 24 | set(MINGW 1) 25 | endif() 26 | set(CMAKE_C_COMPILER_ID_RUN 1) 27 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c) 28 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 29 | set(CMAKE_C_LINKER_PREFERENCE 10) 30 | 31 | # Save compiler ABI information. 32 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 33 | set(CMAKE_C_COMPILER_ABI "ELF") 34 | set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 35 | 36 | if(CMAKE_C_SIZEOF_DATA_PTR) 37 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 38 | endif() 39 | 40 | if(CMAKE_C_COMPILER_ABI) 41 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 42 | endif() 43 | 44 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 45 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 46 | endif() 47 | 48 | 49 | 50 | 51 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "c") 52 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") 53 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_CXX_COMPILER "/usr/bin/c++") 2 | set(CMAKE_CXX_COMPILER_ARG1 "") 3 | set(CMAKE_CXX_COMPILER_ID "GNU") 4 | set(CMAKE_CXX_COMPILER_VERSION "4.8.4") 5 | set(CMAKE_CXX_PLATFORM_ID "Linux") 6 | 7 | set(CMAKE_AR "/usr/bin/ar") 8 | set(CMAKE_RANLIB "/usr/bin/ranlib") 9 | set(CMAKE_LINKER "/usr/bin/ld") 10 | set(CMAKE_COMPILER_IS_GNUCXX 1) 11 | set(CMAKE_CXX_COMPILER_LOADED 1) 12 | set(CMAKE_CXX_COMPILER_WORKS TRUE) 13 | set(CMAKE_CXX_ABI_COMPILED TRUE) 14 | set(CMAKE_COMPILER_IS_MINGW ) 15 | set(CMAKE_COMPILER_IS_CYGWIN ) 16 | if(CMAKE_COMPILER_IS_CYGWIN) 17 | set(CYGWIN 1) 18 | set(UNIX 1) 19 | endif() 20 | 21 | set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") 22 | 23 | if(CMAKE_COMPILER_IS_MINGW) 24 | set(MINGW 1) 25 | endif() 26 | set(CMAKE_CXX_COMPILER_ID_RUN 1) 27 | set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) 28 | set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) 29 | set(CMAKE_CXX_LINKER_PREFERENCE 30) 30 | set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) 31 | 32 | # Save compiler ABI information. 33 | set(CMAKE_CXX_SIZEOF_DATA_PTR "8") 34 | set(CMAKE_CXX_COMPILER_ABI "ELF") 35 | set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 36 | 37 | if(CMAKE_CXX_SIZEOF_DATA_PTR) 38 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") 39 | endif() 40 | 41 | if(CMAKE_CXX_COMPILER_ABI) 42 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") 43 | endif() 44 | 45 | if(CMAKE_CXX_LIBRARY_ARCHITECTURE) 46 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 47 | endif() 48 | 49 | 50 | 51 | 52 | set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;c") 53 | set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") 54 | set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reguix/HttpServer/32901bd5a72430fb8588eb503978137e02d0df96/WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Reguix/HttpServer/32901bd5a72430fb8588eb503978137e02d0df96/WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/2.8.12.2/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Linux-4.4.0-112-generic") 2 | set(CMAKE_HOST_SYSTEM_NAME "Linux") 3 | set(CMAKE_HOST_SYSTEM_VERSION "4.4.0-112-generic") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Linux-4.4.0-112-generic") 9 | set(CMAKE_SYSTEM_NAME "Linux") 10 | set(CMAKE_SYSTEM_VERSION "4.4.0-112-generic") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | # error "A C++ compiler has been selected for C." 3 | #endif 4 | 5 | /* Version number components: V=Version, R=Revision, P=Patch 6 | Version date components: YYYY=Year, MM=Month, DD=Day */ 7 | 8 | #if defined(__18CXX) 9 | # define ID_VOID_MAIN 10 | #endif 11 | 12 | #if defined(__INTEL_COMPILER) || defined(__ICC) 13 | # define COMPILER_ID "Intel" 14 | /* __INTEL_COMPILER = VRP */ 15 | # define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) 16 | # define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) 17 | # define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) 18 | # if defined(__INTEL_COMPILER_BUILD_DATE) 19 | /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ 20 | # define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) 21 | # endif 22 | 23 | #elif defined(__PATHCC__) 24 | # define COMPILER_ID "PathScale" 25 | # define COMPILER_VERSION_MAJOR DEC(__PATHCC__) 26 | # define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) 27 | # if defined(__PATHCC_PATCHLEVEL__) 28 | # define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) 29 | # endif 30 | 31 | #elif defined(__clang__) 32 | # define COMPILER_ID "Clang" 33 | # define COMPILER_VERSION_MAJOR DEC(__clang_major__) 34 | # define COMPILER_VERSION_MINOR DEC(__clang_minor__) 35 | # define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) 36 | 37 | #elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) 38 | # define COMPILER_ID "Embarcadero" 39 | # define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) 40 | # define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) 41 | # define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) 42 | 43 | #elif defined(__BORLANDC__) 44 | # define COMPILER_ID "Borland" 45 | /* __BORLANDC__ = 0xVRR */ 46 | # define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) 47 | # define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) 48 | 49 | #elif defined(__WATCOMC__) 50 | # define COMPILER_ID "Watcom" 51 | /* __WATCOMC__ = VVRR */ 52 | # define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) 53 | # define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) 54 | 55 | #elif defined(__SUNPRO_C) 56 | # define COMPILER_ID "SunPro" 57 | # if __SUNPRO_C >= 0x5100 58 | /* __SUNPRO_C = 0xVRRP */ 59 | # define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) 60 | # define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) 61 | # define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) 62 | # else 63 | /* __SUNPRO_C = 0xVRP */ 64 | # define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) 65 | # define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) 66 | # define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) 67 | # endif 68 | 69 | #elif defined(__HP_cc) 70 | # define COMPILER_ID "HP" 71 | /* __HP_cc = VVRRPP */ 72 | # define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) 73 | # define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) 74 | # define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) 75 | 76 | #elif defined(__DECC) 77 | # define COMPILER_ID "Compaq" 78 | /* __DECC_VER = VVRRTPPPP */ 79 | # define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) 80 | # define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) 81 | # define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) 82 | 83 | #elif defined(__IBMC__) 84 | # if defined(__COMPILER_VER__) 85 | # define COMPILER_ID "zOS" 86 | # else 87 | # if __IBMC__ >= 800 88 | # define COMPILER_ID "XL" 89 | # else 90 | # define COMPILER_ID "VisualAge" 91 | # endif 92 | /* __IBMC__ = VRP */ 93 | # define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) 94 | # define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) 95 | # define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) 96 | # endif 97 | 98 | #elif defined(__PGI) 99 | # define COMPILER_ID "PGI" 100 | # define COMPILER_VERSION_MAJOR DEC(__PGIC__) 101 | # define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) 102 | # if defined(__PGIC_PATCHLEVEL__) 103 | # define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) 104 | # endif 105 | 106 | #elif defined(_CRAYC) 107 | # define COMPILER_ID "Cray" 108 | # define COMPILER_VERSION_MAJOR DEC(_RELEASE) 109 | # define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) 110 | 111 | #elif defined(__TI_COMPILER_VERSION__) 112 | # define COMPILER_ID "TI" 113 | /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ 114 | # define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) 115 | # define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) 116 | # define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) 117 | 118 | #elif defined(__TINYC__) 119 | # define COMPILER_ID "TinyCC" 120 | 121 | #elif defined(__SCO_VERSION__) 122 | # define COMPILER_ID "SCO" 123 | 124 | #elif defined(__GNUC__) 125 | # define COMPILER_ID "GNU" 126 | # define COMPILER_VERSION_MAJOR DEC(__GNUC__) 127 | # define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) 128 | # if defined(__GNUC_PATCHLEVEL__) 129 | # define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) 130 | # endif 131 | 132 | #elif defined(_MSC_VER) 133 | # define COMPILER_ID "MSVC" 134 | /* _MSC_VER = VVRR */ 135 | # define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) 136 | # define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) 137 | # if defined(_MSC_FULL_VER) 138 | # if _MSC_VER >= 1400 139 | /* _MSC_FULL_VER = VVRRPPPPP */ 140 | # define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) 141 | # else 142 | /* _MSC_FULL_VER = VVRRPPPP */ 143 | # define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) 144 | # endif 145 | # endif 146 | # if defined(_MSC_BUILD) 147 | # define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) 148 | # endif 149 | 150 | /* Analog VisualDSP++ >= 4.5.6 */ 151 | #elif defined(__VISUALDSPVERSION__) 152 | # define COMPILER_ID "ADSP" 153 | /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ 154 | # define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) 155 | # define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) 156 | # define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) 157 | 158 | /* Analog VisualDSP++ < 4.5.6 */ 159 | #elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) 160 | # define COMPILER_ID "ADSP" 161 | 162 | /* IAR Systems compiler for embedded systems. 163 | http://www.iar.com */ 164 | #elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) 165 | # define COMPILER_ID "IAR" 166 | 167 | /* sdcc, the small devices C compiler for embedded systems, 168 | http://sdcc.sourceforge.net */ 169 | #elif defined(SDCC) 170 | # define COMPILER_ID "SDCC" 171 | /* SDCC = VRP */ 172 | # define COMPILER_VERSION_MAJOR DEC(SDCC/100) 173 | # define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) 174 | # define COMPILER_VERSION_PATCH DEC(SDCC % 10) 175 | 176 | #elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) 177 | # define COMPILER_ID "MIPSpro" 178 | # if defined(_SGI_COMPILER_VERSION) 179 | /* _SGI_COMPILER_VERSION = VRP */ 180 | # define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) 181 | # define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) 182 | # define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) 183 | # else 184 | /* _COMPILER_VERSION = VRP */ 185 | # define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) 186 | # define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) 187 | # define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) 188 | # endif 189 | 190 | /* This compiler is either not known or is too old to define an 191 | identification macro. Try to identify the platform and guess that 192 | it is the native compiler. */ 193 | #elif defined(__sgi) 194 | # define COMPILER_ID "MIPSpro" 195 | 196 | #elif defined(__hpux) || defined(__hpua) 197 | # define COMPILER_ID "HP" 198 | 199 | #else /* unknown compiler */ 200 | # define COMPILER_ID "" 201 | 202 | #endif 203 | 204 | /* Construct the string literal in pieces to prevent the source from 205 | getting matched. Store it in a pointer rather than an array 206 | because some compilers will just produce instructions to fill the 207 | array rather than assigning a pointer to a static array. */ 208 | char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; 209 | 210 | /* Identify known platforms by name. */ 211 | #if defined(__linux) || defined(__linux__) || defined(linux) 212 | # define PLATFORM_ID "Linux" 213 | 214 | #elif defined(__CYGWIN__) 215 | # define PLATFORM_ID "Cygwin" 216 | 217 | #elif defined(__MINGW32__) 218 | # define PLATFORM_ID "MinGW" 219 | 220 | #elif defined(__APPLE__) 221 | # define PLATFORM_ID "Darwin" 222 | 223 | #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 224 | # define PLATFORM_ID "Windows" 225 | 226 | #elif defined(__FreeBSD__) || defined(__FreeBSD) 227 | # define PLATFORM_ID "FreeBSD" 228 | 229 | #elif defined(__NetBSD__) || defined(__NetBSD) 230 | # define PLATFORM_ID "NetBSD" 231 | 232 | #elif defined(__OpenBSD__) || defined(__OPENBSD) 233 | # define PLATFORM_ID "OpenBSD" 234 | 235 | #elif defined(__sun) || defined(sun) 236 | # define PLATFORM_ID "SunOS" 237 | 238 | #elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) 239 | # define PLATFORM_ID "AIX" 240 | 241 | #elif defined(__sgi) || defined(__sgi__) || defined(_SGI) 242 | # define PLATFORM_ID "IRIX" 243 | 244 | #elif defined(__hpux) || defined(__hpux__) 245 | # define PLATFORM_ID "HP-UX" 246 | 247 | #elif defined(__HAIKU__) 248 | # define PLATFORM_ID "Haiku" 249 | 250 | #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) 251 | # define PLATFORM_ID "BeOS" 252 | 253 | #elif defined(__QNX__) || defined(__QNXNTO__) 254 | # define PLATFORM_ID "QNX" 255 | 256 | #elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) 257 | # define PLATFORM_ID "Tru64" 258 | 259 | #elif defined(__riscos) || defined(__riscos__) 260 | # define PLATFORM_ID "RISCos" 261 | 262 | #elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) 263 | # define PLATFORM_ID "SINIX" 264 | 265 | #elif defined(__UNIX_SV__) 266 | # define PLATFORM_ID "UNIX_SV" 267 | 268 | #elif defined(__bsdos__) 269 | # define PLATFORM_ID "BSDOS" 270 | 271 | #elif defined(_MPRAS) || defined(MPRAS) 272 | # define PLATFORM_ID "MP-RAS" 273 | 274 | #elif defined(__osf) || defined(__osf__) 275 | # define PLATFORM_ID "OSF1" 276 | 277 | #elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) 278 | # define PLATFORM_ID "SCO_SV" 279 | 280 | #elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) 281 | # define PLATFORM_ID "ULTRIX" 282 | 283 | #elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) 284 | # define PLATFORM_ID "Xenix" 285 | 286 | #else /* unknown platform */ 287 | # define PLATFORM_ID "" 288 | 289 | #endif 290 | 291 | /* For windows compilers MSVC and Intel we can determine 292 | the architecture of the compiler being used. This is because 293 | the compilers do not have flags that can change the architecture, 294 | but rather depend on which compiler is being used 295 | */ 296 | #if defined(_WIN32) && defined(_MSC_VER) 297 | # if defined(_M_IA64) 298 | # define ARCHITECTURE_ID "IA64" 299 | 300 | # elif defined(_M_X64) || defined(_M_AMD64) 301 | # define ARCHITECTURE_ID "x64" 302 | 303 | # elif defined(_M_IX86) 304 | # define ARCHITECTURE_ID "X86" 305 | 306 | # elif defined(_M_ARM) 307 | # define ARCHITECTURE_ID "ARM" 308 | 309 | # elif defined(_M_MIPS) 310 | # define ARCHITECTURE_ID "MIPS" 311 | 312 | # elif defined(_M_SH) 313 | # define ARCHITECTURE_ID "SHx" 314 | 315 | # else /* unknown architecture */ 316 | # define ARCHITECTURE_ID "" 317 | # endif 318 | 319 | #else 320 | # define ARCHITECTURE_ID "" 321 | #endif 322 | 323 | /* Convert integer to decimal digit literals. */ 324 | #define DEC(n) \ 325 | ('0' + (((n) / 10000000)%10)), \ 326 | ('0' + (((n) / 1000000)%10)), \ 327 | ('0' + (((n) / 100000)%10)), \ 328 | ('0' + (((n) / 10000)%10)), \ 329 | ('0' + (((n) / 1000)%10)), \ 330 | ('0' + (((n) / 100)%10)), \ 331 | ('0' + (((n) / 10)%10)), \ 332 | ('0' + ((n) % 10)) 333 | 334 | /* Convert integer to hex digit literals. */ 335 | #define HEX(n) \ 336 | ('0' + ((n)>>28 & 0xF)), \ 337 | ('0' + ((n)>>24 & 0xF)), \ 338 | ('0' + ((n)>>20 & 0xF)), \ 339 | ('0' + ((n)>>16 & 0xF)), \ 340 | ('0' + ((n)>>12 & 0xF)), \ 341 | ('0' + ((n)>>8 & 0xF)), \ 342 | ('0' + ((n)>>4 & 0xF)), \ 343 | ('0' + ((n) & 0xF)) 344 | 345 | /* Construct a string literal encoding the version number components. */ 346 | #ifdef COMPILER_VERSION_MAJOR 347 | char const info_version[] = { 348 | 'I', 'N', 'F', 'O', ':', 349 | 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', 350 | COMPILER_VERSION_MAJOR, 351 | # ifdef COMPILER_VERSION_MINOR 352 | '.', COMPILER_VERSION_MINOR, 353 | # ifdef COMPILER_VERSION_PATCH 354 | '.', COMPILER_VERSION_PATCH, 355 | # ifdef COMPILER_VERSION_TWEAK 356 | '.', COMPILER_VERSION_TWEAK, 357 | # endif 358 | # endif 359 | # endif 360 | ']','\0'}; 361 | #endif 362 | 363 | /* Construct the string literal in pieces to prevent the source from 364 | getting matched. Store it in a pointer rather than an array 365 | because some compilers will just produce instructions to fill the 366 | array rather than assigning a pointer to a static array. */ 367 | char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; 368 | char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; 369 | 370 | 371 | 372 | /*--------------------------------------------------------------------------*/ 373 | 374 | #ifdef ID_VOID_MAIN 375 | void main() {} 376 | #else 377 | int main(int argc, char* argv[]) 378 | { 379 | int require = 0; 380 | require += info_compiler[argc]; 381 | require += info_platform[argc]; 382 | require += info_arch[argc]; 383 | #ifdef COMPILER_VERSION_MAJOR 384 | require += info_version[argc]; 385 | #endif 386 | (void)argv; 387 | return require; 388 | } 389 | #endif 390 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp: -------------------------------------------------------------------------------- 1 | /* This source file must have a .cpp extension so that all C++ compilers 2 | recognize the extension without flags. Borland does not know .cxx for 3 | example. */ 4 | #ifndef __cplusplus 5 | # error "A C compiler has been selected for C++." 6 | #endif 7 | 8 | /* Version number components: V=Version, R=Revision, P=Patch 9 | Version date components: YYYY=Year, MM=Month, DD=Day */ 10 | 11 | #if defined(__COMO__) 12 | # define COMPILER_ID "Comeau" 13 | /* __COMO_VERSION__ = VRR */ 14 | # define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100) 15 | # define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100) 16 | 17 | #elif defined(__INTEL_COMPILER) || defined(__ICC) 18 | # define COMPILER_ID "Intel" 19 | /* __INTEL_COMPILER = VRP */ 20 | # define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) 21 | # define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) 22 | # define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) 23 | # if defined(__INTEL_COMPILER_BUILD_DATE) 24 | /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ 25 | # define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) 26 | # endif 27 | 28 | #elif defined(__PATHCC__) 29 | # define COMPILER_ID "PathScale" 30 | # define COMPILER_VERSION_MAJOR DEC(__PATHCC__) 31 | # define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) 32 | # if defined(__PATHCC_PATCHLEVEL__) 33 | # define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) 34 | # endif 35 | 36 | #elif defined(__clang__) 37 | # define COMPILER_ID "Clang" 38 | # define COMPILER_VERSION_MAJOR DEC(__clang_major__) 39 | # define COMPILER_VERSION_MINOR DEC(__clang_minor__) 40 | # define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) 41 | 42 | #elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) 43 | # define COMPILER_ID "Embarcadero" 44 | # define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) 45 | # define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) 46 | # define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) 47 | 48 | #elif defined(__BORLANDC__) 49 | # define COMPILER_ID "Borland" 50 | /* __BORLANDC__ = 0xVRR */ 51 | # define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) 52 | # define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) 53 | 54 | #elif defined(__WATCOMC__) 55 | # define COMPILER_ID "Watcom" 56 | /* __WATCOMC__ = VVRR */ 57 | # define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) 58 | # define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) 59 | 60 | #elif defined(__SUNPRO_CC) 61 | # define COMPILER_ID "SunPro" 62 | # if __SUNPRO_CC >= 0x5100 63 | /* __SUNPRO_CC = 0xVRRP */ 64 | # define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) 65 | # define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) 66 | # define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) 67 | # else 68 | /* __SUNPRO_CC = 0xVRP */ 69 | # define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) 70 | # define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) 71 | # define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) 72 | # endif 73 | 74 | #elif defined(__HP_aCC) 75 | # define COMPILER_ID "HP" 76 | /* __HP_aCC = VVRRPP */ 77 | # define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) 78 | # define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) 79 | # define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) 80 | 81 | #elif defined(__DECCXX) 82 | # define COMPILER_ID "Compaq" 83 | /* __DECCXX_VER = VVRRTPPPP */ 84 | # define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) 85 | # define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) 86 | # define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) 87 | 88 | #elif defined(__IBMCPP__) 89 | # if defined(__COMPILER_VER__) 90 | # define COMPILER_ID "zOS" 91 | # else 92 | # if __IBMCPP__ >= 800 93 | # define COMPILER_ID "XL" 94 | # else 95 | # define COMPILER_ID "VisualAge" 96 | # endif 97 | /* __IBMCPP__ = VRP */ 98 | # define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) 99 | # define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) 100 | # define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) 101 | # endif 102 | 103 | #elif defined(__PGI) 104 | # define COMPILER_ID "PGI" 105 | # define COMPILER_VERSION_MAJOR DEC(__PGIC__) 106 | # define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) 107 | # if defined(__PGIC_PATCHLEVEL__) 108 | # define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) 109 | # endif 110 | 111 | #elif defined(_CRAYC) 112 | # define COMPILER_ID "Cray" 113 | # define COMPILER_VERSION_MAJOR DEC(_RELEASE) 114 | # define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) 115 | 116 | #elif defined(__TI_COMPILER_VERSION__) 117 | # define COMPILER_ID "TI" 118 | /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ 119 | # define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) 120 | # define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) 121 | # define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) 122 | 123 | #elif defined(__SCO_VERSION__) 124 | # define COMPILER_ID "SCO" 125 | 126 | #elif defined(__GNUC__) 127 | # define COMPILER_ID "GNU" 128 | # define COMPILER_VERSION_MAJOR DEC(__GNUC__) 129 | # define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) 130 | # if defined(__GNUC_PATCHLEVEL__) 131 | # define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) 132 | # endif 133 | 134 | #elif defined(_MSC_VER) 135 | # define COMPILER_ID "MSVC" 136 | /* _MSC_VER = VVRR */ 137 | # define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) 138 | # define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) 139 | # if defined(_MSC_FULL_VER) 140 | # if _MSC_VER >= 1400 141 | /* _MSC_FULL_VER = VVRRPPPPP */ 142 | # define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) 143 | # else 144 | /* _MSC_FULL_VER = VVRRPPPP */ 145 | # define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) 146 | # endif 147 | # endif 148 | # if defined(_MSC_BUILD) 149 | # define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) 150 | # endif 151 | 152 | /* Analog VisualDSP++ >= 4.5.6 */ 153 | #elif defined(__VISUALDSPVERSION__) 154 | # define COMPILER_ID "ADSP" 155 | /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ 156 | # define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) 157 | # define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) 158 | # define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) 159 | 160 | /* Analog VisualDSP++ < 4.5.6 */ 161 | #elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) 162 | # define COMPILER_ID "ADSP" 163 | 164 | /* IAR Systems compiler for embedded systems. 165 | http://www.iar.com */ 166 | #elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) 167 | # define COMPILER_ID "IAR" 168 | 169 | #elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) 170 | # define COMPILER_ID "MIPSpro" 171 | # if defined(_SGI_COMPILER_VERSION) 172 | /* _SGI_COMPILER_VERSION = VRP */ 173 | # define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) 174 | # define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) 175 | # define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) 176 | # else 177 | /* _COMPILER_VERSION = VRP */ 178 | # define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) 179 | # define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) 180 | # define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) 181 | # endif 182 | 183 | /* This compiler is either not known or is too old to define an 184 | identification macro. Try to identify the platform and guess that 185 | it is the native compiler. */ 186 | #elif defined(__sgi) 187 | # define COMPILER_ID "MIPSpro" 188 | 189 | #elif defined(__hpux) || defined(__hpua) 190 | # define COMPILER_ID "HP" 191 | 192 | #else /* unknown compiler */ 193 | # define COMPILER_ID "" 194 | 195 | #endif 196 | 197 | /* Construct the string literal in pieces to prevent the source from 198 | getting matched. Store it in a pointer rather than an array 199 | because some compilers will just produce instructions to fill the 200 | array rather than assigning a pointer to a static array. */ 201 | char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; 202 | 203 | /* Identify known platforms by name. */ 204 | #if defined(__linux) || defined(__linux__) || defined(linux) 205 | # define PLATFORM_ID "Linux" 206 | 207 | #elif defined(__CYGWIN__) 208 | # define PLATFORM_ID "Cygwin" 209 | 210 | #elif defined(__MINGW32__) 211 | # define PLATFORM_ID "MinGW" 212 | 213 | #elif defined(__APPLE__) 214 | # define PLATFORM_ID "Darwin" 215 | 216 | #elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) 217 | # define PLATFORM_ID "Windows" 218 | 219 | #elif defined(__FreeBSD__) || defined(__FreeBSD) 220 | # define PLATFORM_ID "FreeBSD" 221 | 222 | #elif defined(__NetBSD__) || defined(__NetBSD) 223 | # define PLATFORM_ID "NetBSD" 224 | 225 | #elif defined(__OpenBSD__) || defined(__OPENBSD) 226 | # define PLATFORM_ID "OpenBSD" 227 | 228 | #elif defined(__sun) || defined(sun) 229 | # define PLATFORM_ID "SunOS" 230 | 231 | #elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) 232 | # define PLATFORM_ID "AIX" 233 | 234 | #elif defined(__sgi) || defined(__sgi__) || defined(_SGI) 235 | # define PLATFORM_ID "IRIX" 236 | 237 | #elif defined(__hpux) || defined(__hpux__) 238 | # define PLATFORM_ID "HP-UX" 239 | 240 | #elif defined(__HAIKU__) 241 | # define PLATFORM_ID "Haiku" 242 | 243 | #elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) 244 | # define PLATFORM_ID "BeOS" 245 | 246 | #elif defined(__QNX__) || defined(__QNXNTO__) 247 | # define PLATFORM_ID "QNX" 248 | 249 | #elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) 250 | # define PLATFORM_ID "Tru64" 251 | 252 | #elif defined(__riscos) || defined(__riscos__) 253 | # define PLATFORM_ID "RISCos" 254 | 255 | #elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) 256 | # define PLATFORM_ID "SINIX" 257 | 258 | #elif defined(__UNIX_SV__) 259 | # define PLATFORM_ID "UNIX_SV" 260 | 261 | #elif defined(__bsdos__) 262 | # define PLATFORM_ID "BSDOS" 263 | 264 | #elif defined(_MPRAS) || defined(MPRAS) 265 | # define PLATFORM_ID "MP-RAS" 266 | 267 | #elif defined(__osf) || defined(__osf__) 268 | # define PLATFORM_ID "OSF1" 269 | 270 | #elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) 271 | # define PLATFORM_ID "SCO_SV" 272 | 273 | #elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) 274 | # define PLATFORM_ID "ULTRIX" 275 | 276 | #elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) 277 | # define PLATFORM_ID "Xenix" 278 | 279 | #else /* unknown platform */ 280 | # define PLATFORM_ID "" 281 | 282 | #endif 283 | 284 | /* For windows compilers MSVC and Intel we can determine 285 | the architecture of the compiler being used. This is because 286 | the compilers do not have flags that can change the architecture, 287 | but rather depend on which compiler is being used 288 | */ 289 | #if defined(_WIN32) && defined(_MSC_VER) 290 | # if defined(_M_IA64) 291 | # define ARCHITECTURE_ID "IA64" 292 | 293 | # elif defined(_M_X64) || defined(_M_AMD64) 294 | # define ARCHITECTURE_ID "x64" 295 | 296 | # elif defined(_M_IX86) 297 | # define ARCHITECTURE_ID "X86" 298 | 299 | # elif defined(_M_ARM) 300 | # define ARCHITECTURE_ID "ARM" 301 | 302 | # elif defined(_M_MIPS) 303 | # define ARCHITECTURE_ID "MIPS" 304 | 305 | # elif defined(_M_SH) 306 | # define ARCHITECTURE_ID "SHx" 307 | 308 | # else /* unknown architecture */ 309 | # define ARCHITECTURE_ID "" 310 | # endif 311 | 312 | #else 313 | # define ARCHITECTURE_ID "" 314 | #endif 315 | 316 | /* Convert integer to decimal digit literals. */ 317 | #define DEC(n) \ 318 | ('0' + (((n) / 10000000)%10)), \ 319 | ('0' + (((n) / 1000000)%10)), \ 320 | ('0' + (((n) / 100000)%10)), \ 321 | ('0' + (((n) / 10000)%10)), \ 322 | ('0' + (((n) / 1000)%10)), \ 323 | ('0' + (((n) / 100)%10)), \ 324 | ('0' + (((n) / 10)%10)), \ 325 | ('0' + ((n) % 10)) 326 | 327 | /* Convert integer to hex digit literals. */ 328 | #define HEX(n) \ 329 | ('0' + ((n)>>28 & 0xF)), \ 330 | ('0' + ((n)>>24 & 0xF)), \ 331 | ('0' + ((n)>>20 & 0xF)), \ 332 | ('0' + ((n)>>16 & 0xF)), \ 333 | ('0' + ((n)>>12 & 0xF)), \ 334 | ('0' + ((n)>>8 & 0xF)), \ 335 | ('0' + ((n)>>4 & 0xF)), \ 336 | ('0' + ((n) & 0xF)) 337 | 338 | /* Construct a string literal encoding the version number components. */ 339 | #ifdef COMPILER_VERSION_MAJOR 340 | char const info_version[] = { 341 | 'I', 'N', 'F', 'O', ':', 342 | 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', 343 | COMPILER_VERSION_MAJOR, 344 | # ifdef COMPILER_VERSION_MINOR 345 | '.', COMPILER_VERSION_MINOR, 346 | # ifdef COMPILER_VERSION_PATCH 347 | '.', COMPILER_VERSION_PATCH, 348 | # ifdef COMPILER_VERSION_TWEAK 349 | '.', COMPILER_VERSION_TWEAK, 350 | # endif 351 | # endif 352 | # endif 353 | ']','\0'}; 354 | #endif 355 | 356 | /* Construct the string literal in pieces to prevent the source from 357 | getting matched. Store it in a pointer rather than an array 358 | because some compilers will just produce instructions to fill the 359 | array rather than assigning a pointer to a static array. */ 360 | char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; 361 | char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; 362 | 363 | 364 | 365 | /*--------------------------------------------------------------------------*/ 366 | 367 | int main(int argc, char* argv[]) 368 | { 369 | int require = 0; 370 | require += info_compiler[argc]; 371 | require += info_platform[argc]; 372 | #ifdef COMPILER_VERSION_MAJOR 373 | require += info_version[argc]; 374 | #endif 375 | (void)argv; 376 | return require; 377 | } 378 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/CMakeError.log: -------------------------------------------------------------------------------- 1 | Determining if the pthread_create exist failed with the following output: 2 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 3 | 4 | Run Build Command:/usr/bin/make "cmTryCompileExec2725160972/fast" 5 | /usr/bin/make -f CMakeFiles/cmTryCompileExec2725160972.dir/build.make CMakeFiles/cmTryCompileExec2725160972.dir/build 6 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 7 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 8 | Building C object CMakeFiles/cmTryCompileExec2725160972.dir/CheckSymbolExists.c.o 9 | /usr/bin/cc -o CMakeFiles/cmTryCompileExec2725160972.dir/CheckSymbolExists.c.o -c /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CheckSymbolExists.c 10 | Linking C executable cmTryCompileExec2725160972 11 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2725160972.dir/link.txt --verbose=1 12 | /usr/bin/cc CMakeFiles/cmTryCompileExec2725160972.dir/CheckSymbolExists.c.o -o cmTryCompileExec2725160972 -rdynamic 13 | CMakeFiles/cmTryCompileExec2725160972.dir/CheckSymbolExists.c.o: In function `main': 14 | CheckSymbolExists.c:(.text+0x16): undefined reference to `pthread_create' 15 | collect2: error: ld returned 1 exit status 16 | make[1]: *** [cmTryCompileExec2725160972] Error 1 17 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 18 | make: *** [cmTryCompileExec2725160972/fast] Error 2 19 | 20 | File /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CheckSymbolExists.c: 21 | /* */ 22 | #include 23 | 24 | int main(int argc, char** argv) 25 | { 26 | (void)argv; 27 | #ifndef pthread_create 28 | return ((int*)(&pthread_create))[argc]; 29 | #else 30 | (void)argc; 31 | return 0; 32 | #endif 33 | } 34 | 35 | Determining if the function pthread_create exists in the pthreads failed with the following output: 36 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 37 | 38 | Run Build Command:/usr/bin/make "cmTryCompileExec2469824604/fast" 39 | /usr/bin/make -f CMakeFiles/cmTryCompileExec2469824604.dir/build.make CMakeFiles/cmTryCompileExec2469824604.dir/build 40 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 41 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 42 | Building C object CMakeFiles/cmTryCompileExec2469824604.dir/CheckFunctionExists.c.o 43 | /usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -o CMakeFiles/cmTryCompileExec2469824604.dir/CheckFunctionExists.c.o -c /usr/share/cmake-2.8/Modules/CheckFunctionExists.c 44 | Linking C executable cmTryCompileExec2469824604 45 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2469824604.dir/link.txt --verbose=1 46 | /usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create CMakeFiles/cmTryCompileExec2469824604.dir/CheckFunctionExists.c.o -o cmTryCompileExec2469824604 -rdynamic -lpthreads 47 | /usr/bin/ld: cannot find -lpthreads 48 | collect2: error: ld returned 1 exit status 49 | make[1]: *** [cmTryCompileExec2469824604] Error 1 50 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 51 | make: *** [cmTryCompileExec2469824604/fast] Error 2 52 | 53 | 54 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/CMakeOutput.log: -------------------------------------------------------------------------------- 1 | The system is: Linux - 4.4.0-112-generic - x86_64 2 | Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. 3 | Compiler: /usr/bin/cc 4 | Build flags: 5 | Id flags: 6 | 7 | The output was: 8 | 0 9 | 10 | 11 | Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" 12 | 13 | The C compiler identification is GNU, found in "/home/linya/beifen/myserver/tests/build/release/CMakeFiles/2.8.12.2/CompilerIdC/a.out" 14 | 15 | Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. 16 | Compiler: /usr/bin/c++ 17 | Build flags: 18 | Id flags: 19 | 20 | The output was: 21 | 0 22 | 23 | 24 | Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" 25 | 26 | The CXX compiler identification is GNU, found in "/home/linya/beifen/myserver/tests/build/release/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out" 27 | 28 | Determining if the C compiler works passed with the following output: 29 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 30 | 31 | Run Build Command:/usr/bin/make "cmTryCompileExec1048658521/fast" 32 | /usr/bin/make -f CMakeFiles/cmTryCompileExec1048658521.dir/build.make CMakeFiles/cmTryCompileExec1048658521.dir/build 33 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 34 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 35 | Building C object CMakeFiles/cmTryCompileExec1048658521.dir/testCCompiler.c.o 36 | /usr/bin/cc -o CMakeFiles/cmTryCompileExec1048658521.dir/testCCompiler.c.o -c /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/testCCompiler.c 37 | Linking C executable cmTryCompileExec1048658521 38 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec1048658521.dir/link.txt --verbose=1 39 | /usr/bin/cc CMakeFiles/cmTryCompileExec1048658521.dir/testCCompiler.c.o -o cmTryCompileExec1048658521 -rdynamic 40 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 41 | 42 | 43 | Detecting C compiler ABI info compiled with the following output: 44 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 45 | 46 | Run Build Command:/usr/bin/make "cmTryCompileExec3864032145/fast" 47 | /usr/bin/make -f CMakeFiles/cmTryCompileExec3864032145.dir/build.make CMakeFiles/cmTryCompileExec3864032145.dir/build 48 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 49 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 50 | Building C object CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o 51 | /usr/bin/cc -o CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c 52 | Linking C executable cmTryCompileExec3864032145 53 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3864032145.dir/link.txt --verbose=1 54 | /usr/bin/cc -v CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3864032145 -rdynamic 55 | Using built-in specs. 56 | COLLECT_GCC=/usr/bin/cc 57 | COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper 58 | Target: x86_64-linux-gnu 59 | Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.3' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu 60 | Thread model: posix 61 | gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) 62 | COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/ 63 | LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/ 64 | COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3864032145' '-rdynamic' '-mtune=generic' '-march=x86-64' 65 | /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3864032145 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o 66 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 67 | 68 | 69 | Parsed C implicit link information from above output: 70 | link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] 71 | ignore line: [Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp] 72 | ignore line: [] 73 | ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec3864032145/fast"] 74 | ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec3864032145.dir/build.make CMakeFiles/cmTryCompileExec3864032145.dir/build] 75 | ignore line: [make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp'] 76 | ignore line: [/usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1] 77 | ignore line: [Building C object CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o] 78 | ignore line: [/usr/bin/cc -o CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c] 79 | ignore line: [Linking C executable cmTryCompileExec3864032145] 80 | ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3864032145.dir/link.txt --verbose=1] 81 | ignore line: [/usr/bin/cc -v CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3864032145 -rdynamic ] 82 | ignore line: [Using built-in specs.] 83 | ignore line: [COLLECT_GCC=/usr/bin/cc] 84 | ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper] 85 | ignore line: [Target: x86_64-linux-gnu] 86 | ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.3' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] 87 | ignore line: [Thread model: posix] 88 | ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) ] 89 | ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/] 90 | ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/] 91 | ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3864032145' '-rdynamic' '-mtune=generic' '-march=x86-64'] 92 | link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3864032145 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] 93 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore 94 | arg [--sysroot=/] ==> ignore 95 | arg [--build-id] ==> ignore 96 | arg [--eh-frame-hdr] ==> ignore 97 | arg [-m] ==> ignore 98 | arg [elf_x86_64] ==> ignore 99 | arg [--hash-style=gnu] ==> ignore 100 | arg [--as-needed] ==> ignore 101 | arg [-export-dynamic] ==> ignore 102 | arg [-dynamic-linker] ==> ignore 103 | arg [/lib64/ld-linux-x86-64.so.2] ==> ignore 104 | arg [-zrelro] ==> ignore 105 | arg [-o] ==> ignore 106 | arg [cmTryCompileExec3864032145] ==> ignore 107 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore 108 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore 109 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore 110 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] 111 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] 112 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] 113 | arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] 114 | arg [-L/lib/../lib] ==> dir [/lib/../lib] 115 | arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] 116 | arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] 117 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] 118 | arg [CMakeFiles/cmTryCompileExec3864032145.dir/CMakeCCompilerABI.c.o] ==> ignore 119 | arg [-lgcc] ==> lib [gcc] 120 | arg [--as-needed] ==> ignore 121 | arg [-lgcc_s] ==> lib [gcc_s] 122 | arg [--no-as-needed] ==> ignore 123 | arg [-lc] ==> lib [c] 124 | arg [-lgcc] ==> lib [gcc] 125 | arg [--as-needed] ==> ignore 126 | arg [-lgcc_s] ==> lib [gcc_s] 127 | arg [--no-as-needed] ==> ignore 128 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore 129 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore 130 | remove lib [gcc] 131 | remove lib [gcc_s] 132 | remove lib [gcc] 133 | remove lib [gcc_s] 134 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8] 135 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] 136 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib] 137 | collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] 138 | collapse library dir [/lib/../lib] ==> [/lib] 139 | collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] 140 | collapse library dir [/usr/lib/../lib] ==> [/usr/lib] 141 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib] 142 | implicit libs: [c] 143 | implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] 144 | implicit fwks: [] 145 | 146 | 147 | Determining if the CXX compiler works passed with the following output: 148 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 149 | 150 | Run Build Command:/usr/bin/make "cmTryCompileExec3312599426/fast" 151 | /usr/bin/make -f CMakeFiles/cmTryCompileExec3312599426.dir/build.make CMakeFiles/cmTryCompileExec3312599426.dir/build 152 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 153 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 154 | Building CXX object CMakeFiles/cmTryCompileExec3312599426.dir/testCXXCompiler.cxx.o 155 | /usr/bin/c++ -o CMakeFiles/cmTryCompileExec3312599426.dir/testCXXCompiler.cxx.o -c /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/testCXXCompiler.cxx 156 | Linking CXX executable cmTryCompileExec3312599426 157 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3312599426.dir/link.txt --verbose=1 158 | /usr/bin/c++ CMakeFiles/cmTryCompileExec3312599426.dir/testCXXCompiler.cxx.o -o cmTryCompileExec3312599426 -rdynamic 159 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 160 | 161 | 162 | Detecting CXX compiler ABI info compiled with the following output: 163 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 164 | 165 | Run Build Command:/usr/bin/make "cmTryCompileExec1847169327/fast" 166 | /usr/bin/make -f CMakeFiles/cmTryCompileExec1847169327.dir/build.make CMakeFiles/cmTryCompileExec1847169327.dir/build 167 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 168 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 169 | Building CXX object CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o 170 | /usr/bin/c++ -o CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp 171 | Linking CXX executable cmTryCompileExec1847169327 172 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec1847169327.dir/link.txt --verbose=1 173 | /usr/bin/c++ -v CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec1847169327 -rdynamic 174 | Using built-in specs. 175 | COLLECT_GCC=/usr/bin/c++ 176 | COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper 177 | Target: x86_64-linux-gnu 178 | Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.3' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu 179 | Thread model: posix 180 | gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) 181 | COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/ 182 | LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/ 183 | COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec1847169327' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' 184 | /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec1847169327 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o 185 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 186 | 187 | 188 | Parsed CXX implicit link information from above output: 189 | link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] 190 | ignore line: [Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp] 191 | ignore line: [] 192 | ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec1847169327/fast"] 193 | ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec1847169327.dir/build.make CMakeFiles/cmTryCompileExec1847169327.dir/build] 194 | ignore line: [make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp'] 195 | ignore line: [/usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1] 196 | ignore line: [Building CXX object CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o] 197 | ignore line: [/usr/bin/c++ -o CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp] 198 | ignore line: [Linking CXX executable cmTryCompileExec1847169327] 199 | ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec1847169327.dir/link.txt --verbose=1] 200 | ignore line: [/usr/bin/c++ -v CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec1847169327 -rdynamic ] 201 | ignore line: [Using built-in specs.] 202 | ignore line: [COLLECT_GCC=/usr/bin/c++] 203 | ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper] 204 | ignore line: [Target: x86_64-linux-gnu] 205 | ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04.3' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] 206 | ignore line: [Thread model: posix] 207 | ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3) ] 208 | ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/] 209 | ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/] 210 | ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec1847169327' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] 211 | link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec1847169327 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] 212 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore 213 | arg [--sysroot=/] ==> ignore 214 | arg [--build-id] ==> ignore 215 | arg [--eh-frame-hdr] ==> ignore 216 | arg [-m] ==> ignore 217 | arg [elf_x86_64] ==> ignore 218 | arg [--hash-style=gnu] ==> ignore 219 | arg [--as-needed] ==> ignore 220 | arg [-export-dynamic] ==> ignore 221 | arg [-dynamic-linker] ==> ignore 222 | arg [/lib64/ld-linux-x86-64.so.2] ==> ignore 223 | arg [-zrelro] ==> ignore 224 | arg [-o] ==> ignore 225 | arg [cmTryCompileExec1847169327] ==> ignore 226 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore 227 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore 228 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore 229 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] 230 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] 231 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] 232 | arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] 233 | arg [-L/lib/../lib] ==> dir [/lib/../lib] 234 | arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] 235 | arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] 236 | arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] 237 | arg [CMakeFiles/cmTryCompileExec1847169327.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore 238 | arg [-lstdc++] ==> lib [stdc++] 239 | arg [-lm] ==> lib [m] 240 | arg [-lgcc_s] ==> lib [gcc_s] 241 | arg [-lgcc] ==> lib [gcc] 242 | arg [-lc] ==> lib [c] 243 | arg [-lgcc_s] ==> lib [gcc_s] 244 | arg [-lgcc] ==> lib [gcc] 245 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore 246 | arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore 247 | remove lib [gcc_s] 248 | remove lib [gcc] 249 | remove lib [gcc_s] 250 | remove lib [gcc] 251 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8] 252 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] 253 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib] 254 | collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] 255 | collapse library dir [/lib/../lib] ==> [/lib] 256 | collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] 257 | collapse library dir [/usr/lib/../lib] ==> [/usr/lib] 258 | collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib] 259 | implicit libs: [stdc++;m;c] 260 | implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] 261 | implicit fwks: [] 262 | 263 | 264 | Determining if files pthread.h exist passed with the following output: 265 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 266 | 267 | Run Build Command:/usr/bin/make "cmTryCompileExec928567820/fast" 268 | /usr/bin/make -f CMakeFiles/cmTryCompileExec928567820.dir/build.make CMakeFiles/cmTryCompileExec928567820.dir/build 269 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 270 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 271 | Building C object CMakeFiles/cmTryCompileExec928567820.dir/CheckIncludeFiles.c.o 272 | /usr/bin/cc -o CMakeFiles/cmTryCompileExec928567820.dir/CheckIncludeFiles.c.o -c /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CheckIncludeFiles.c 273 | Linking C executable cmTryCompileExec928567820 274 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec928567820.dir/link.txt --verbose=1 275 | /usr/bin/cc CMakeFiles/cmTryCompileExec928567820.dir/CheckIncludeFiles.c.o -o cmTryCompileExec928567820 -rdynamic 276 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 277 | 278 | 279 | Determining if the function pthread_create exists in the pthread passed with the following output: 280 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 281 | 282 | Run Build Command:/usr/bin/make "cmTryCompileExec2113051811/fast" 283 | /usr/bin/make -f CMakeFiles/cmTryCompileExec2113051811.dir/build.make CMakeFiles/cmTryCompileExec2113051811.dir/build 284 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 285 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 286 | Building C object CMakeFiles/cmTryCompileExec2113051811.dir/CheckFunctionExists.c.o 287 | /usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create -o CMakeFiles/cmTryCompileExec2113051811.dir/CheckFunctionExists.c.o -c /usr/share/cmake-2.8/Modules/CheckFunctionExists.c 288 | Linking C executable cmTryCompileExec2113051811 289 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2113051811.dir/link.txt --verbose=1 290 | /usr/bin/cc -DCHECK_FUNCTION_EXISTS=pthread_create CMakeFiles/cmTryCompileExec2113051811.dir/CheckFunctionExists.c.o -o cmTryCompileExec2113051811 -rdynamic -lpthread 291 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 292 | 293 | 294 | Determining if the function accept4 exists passed with the following output: 295 | Change Dir: /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp 296 | 297 | Run Build Command:/usr/bin/make "cmTryCompileExec3459516700/fast" 298 | /usr/bin/make -f CMakeFiles/cmTryCompileExec3459516700.dir/build.make CMakeFiles/cmTryCompileExec3459516700.dir/build 299 | make[1]: Entering directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 300 | /usr/bin/cmake -E cmake_progress_report /home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp/CMakeFiles 1 301 | Building C object CMakeFiles/cmTryCompileExec3459516700.dir/CheckFunctionExists.c.o 302 | /usr/bin/cc -DCHECK_FUNCTION_EXISTS=accept4 -o CMakeFiles/cmTryCompileExec3459516700.dir/CheckFunctionExists.c.o -c /usr/share/cmake-2.8/Modules/CheckFunctionExists.c 303 | Linking C executable cmTryCompileExec3459516700 304 | /usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3459516700.dir/link.txt --verbose=1 305 | /usr/bin/cc -DCHECK_FUNCTION_EXISTS=accept4 CMakeFiles/cmTryCompileExec3459516700.dir/CheckFunctionExists.c.o -o cmTryCompileExec3459516700 -rdynamic 306 | make[1]: Leaving directory `/home/linya/beifen/myserver/tests/build/release/CMakeFiles/CMakeTmp' 307 | 308 | 309 | -------------------------------------------------------------------------------- /WebServer/tests/build/release/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | SOURCE_DIR=`pwd` 6 | BUILD_DIR=${BUILD_DIR:-../build} 7 | BUILD_TYPE=${BUILD_TYPE:-release} 8 | 9 | mkdir -p $BUILD_DIR/$BUILD_TYPE \ 10 | && cd $BUILD_DIR/$BUILD_TYPE \ 11 | && cmake \ 12 | -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ 13 | $SOURCE_DIR \ 14 | && make $* --------------------------------------------------------------------------------