[sylar]C++高性能服务器框架——HttpServer模块

456 阅读3分钟

HttpServer模块概述

封装HttpSession接收请求报文,发送响应报文,该类继承自SocketStream

封装Servlet,虚拟接口,当Server命中某个uri时,执行对应的Servlet

封装HttpServer服务器,继承自TcpServer

HttpSession详解

class HttpSession

HttpSession(构造函数)

HttpSession::HttpSession(Socket::ptr sock, bool owern)
    :SocketStream(sock, owern) {
    
}

recvRequest(接收请求报文)

HttpRequest::ptr HttpSession::recvRequest() {
    // 创建HttpRequestParser
    HttpRequestParser::ptr parser(new HttpRequestParser);
    // 获取缓冲区大小
    uint64_t buff_size = HttpRequestParser::GetHttpRequestBufferSize();
    // 交给智能指针托管
    std::shared_ptr<char> buffer(
        new char[buff_size], [](char* ptr) {
            delete[] ptr;
        });
    char* data = buffer.get();
    int offset = 0;
    do {
        // 在offset后面接着读数据
        int len = read(data + offset, buff_size - offset);
        if (len <= 0) {
            close();
            return nullptr;
        }
        // 当前已经读取的数据长度
        len += offset;
        // 解析缓冲区data中的数据
        // execute会将data向前移动nparse个字节,nparse为已经成功解析的字节数
        size_t nparse = parser->execute(data, len);
        if (parser->hasError()) {
            close();
            return nullptr;
        }
        // 此时data还剩下已经读到的数据 - 解析过的数据
        offset = len - nparse;
        // 缓冲区满了还没解析完
        if (offset == (int)buff_size) {
            close();
            return nullptr;
        }
        // 解析结束
        if (parser->isFinished()) {
            break;
        }
    } while (true);
    // 获得body的长度
    int64_t length = parser->getContentLength();
    if (length > 0) {
        std::string body;
        body.resize(length);
​
        int len = 0;
        // 如果body长度比缓冲区剩余的还大,将缓冲区全部加进来
        if (length >= offset) {
            mempcpy(&body[0], data, offset);
            len = offset;
        } else {
            // 否则将取length
            memcpy(&body[0], data, length);
            len = length;
        }
​
        length -= offset;
        // 缓冲区里的数据也不够,继续读取直到满足length
        if (length > 0) {
            if (readFixSize(&body[len], length) <= 0) {
                close();
                return nullptr;
            }
        }
        // 设置body
        parser->getData()->setBody(body);
    }
    //返回解析完的HttpRequest
    return parser->getData();
}

sendResponse(发送响应报文)

int HttpSession::sendResponse(HttpResponse::ptr rsp) {
    std::stringstream ss;
    ss << *rsp;
    std::string data = ss.str();
    return writeFixSize(data.c_str(), data.size());
}

Servlet详解

class Servlet

抽象类,基类,提供一个纯虚函数。当访问到该servlet时,执行handle方法

virtual int32_t handle(sylar::http::HttpRequest::ptr request
    , sylar::http::HttpResponse::ptr response
    , sylar::http::HttpSession::ptr session) = 0;

mumber(成员变量)

// servlet名字
std::string m_name;

Servlet(构造函数)

Servlet(const std::string& name)
    :m_name(name) {
}

class FunctionServlet

mumber(成员变量)

typedef std::function<int32_t(sylar::http::HttpRequest::ptr request
        , sylar::http::HttpResponse::ptr response
        , sylar::http::HttpSession::ptr session)> callback;
​
// 执行函数
callback m_cb;

FunctionServlet(构造函数)

FunctionServlet::FunctionServlet(callback cb)
    :Servlet("FunctionServlet")
    ,m_cb(cb) {
​
}

handle(执行函数)

int32_t FunctionServlet::handle(sylar::http::HttpRequest::ptr request
    , sylar::http::HttpResponse::ptr response
    , sylar::http::HttpSession::ptr session) {
    return m_cb(request, response, session);
}

class ServletDispatch

Servlet管理类

mumber(成员变量)

// 读写锁
RWMutexType m_mutex;
// uri(/sylar/xxx) -> servlet 精准匹配
std::unordered_map<std::string, Servlet::ptr> m_datas;
// uri(/sylar/*) -> servlet 模糊匹配
std::vector<std::pair<std::string, Servlet::ptr> > m_globs;
// 默认servlet返回404 Not found,所有路径无匹配使用
Servlet::ptr m_default;

ServletDispatch(构造函数)

ServletDispatch::ServletDispatch()
    :Servlet("ServletDispatch") {
    m_default.reset(new NotFoundServlet("sylar/1.0"));
}

handle(执行函数)

int32_t ServletDispatch::handle(sylar::http::HttpRequest::ptr request
    , sylar::http::HttpResponse::ptr response
    , sylar::http::HttpSession::ptr session) {
    auto slt = getMatchedServlet(request->getPath());
    if (slt) {
        slt->handle(request, response, session);
    }
    return 0;
}

addServlet(添加精准Servlet,智能指针)

void ServletDispatch::addServlet(const std::string& uri, Servlet::ptr slt) {
    RWMutexType::WriteLock lock(m_mutex);
    m_datas[uri] = slt;
}

addServlet(添加精准Servlet,回调函数)

void ServletDispatch::addServlet(const std::string& uri, FunctionServlet::callback cb) {
    RWMutexType::WriteLock lock(m_mutex);
    m_datas[uri].reset(new FunctionServlet(cb));
}

addGlobServlet(添加模糊Servlet,智能指针)

void ServletDispatch::addGlobServlet(const std::string& uri, Servlet::ptr slt) {
    RWMutexType::WriteLock lock(m_mutex);
    // 将原先的删除
    for (auto it = m_globs.begin();
        it != m_globs.end(); ++it) {
        if (it->first == uri) {
            m_globs.erase(it);
            break;
        }
    }
    m_globs.push_back(std::make_pair(uri, slt));
}

addServlet(添加模糊Servlet,回调函数)

void ServletDispatch::addGlobServlet(const std::string& uri, FunctionServlet::callback cb) {
    return addGlobServlet(uri, FunctionServlet::ptr(new FunctionServlet(cb)));
}

delServlet(删除精准Servlet)

void ServletDispatch::delServlet(const std::string& uri) {
    RWMutexType::WriteLock lock(m_mutex);
    m_datas.erase(uri);
}

delGlobServlet(删除模糊Servlet)

void ServletDispatch::delGlobServlet(const std::string& uri) {
    RWMutexType::WriteLock lock(m_mutex);
    for (auto it = m_globs.begin();
        it != m_globs.end(); ++it) {
        if (it->first == uri) {
            m_globs.erase(it);
            break;
        }
    }
}

getServlet(返回精准Servlet)

Servlet::ptr ServletDispatch::getServlet(const std::string& uri) {
    RWMutexType::ReadLock lock(m_mutex);
    auto it = m_datas.find(uri);
    return it == m_datas.end() ? nullptr : it->second;
}

getGlobServlet(返回模糊Servlet)

Servlet::ptr ServletDispatch::getGlobServlet(const std::string& uri) {
    RWMutexType::ReadLock lock(m_mutex);
    for (auto it = m_globs.begin();
        it != m_globs.end(); ++it) {
        if (it->first == uri) {
            return it->second;
        }
    }
    return nullptr;
}

getMatchedServlet(匹配Servlet)

Servlet::ptr ServletDispatch::getMatchedServlet(const std::string& uri) {
    RWMutexType::ReadLock lock(m_mutex);
    // 先找精准的Servlet
    auto mit = m_datas.find(uri);
    if (mit != m_datas.end()) {
        return mit->second;
    }
	
    // 再找模糊的Servlet
    for (auto it = m_globs.begin();
        it != m_globs.end(); ++it) {
        // 模糊匹配Servlet
        if (!fnmatch(it->first.c_str(), uri.c_str(), 0)) {
            return it->second;
        }
    }
    
   	// 都没有返回404
    return m_default;
}

class NotFoundServlet

默认返回404

mumber(成员变量)

// 服务器版本名称
std::string m_name;
// body
std::string m_content;

NotFoundServlet(构造函数)

NotFoundServlet::NotFoundServlet(const std::string& name)
    :Servlet("NotFoundServlet")
    ,m_name(name) {
    m_content = "<html><head><title>404 Not Found"
        "</title></head><body><center><h1>404 Not Found</h1></center>"
        "<hr><center>" + name + "</center></body></html>";
}

handle(执行函数)

int32_t NotFoundServlet::handle(sylar::http::HttpRequest::ptr request
    , sylar::http::HttpResponse::ptr response
    , sylar::http::HttpSession::ptr session) {

    response->setStatue(sylar::http::HttpStatus::NOT_FOUND);
    response->setHeader("Server", "sylar/1.0.0");
    response->setHeader("Content-Type", "text/html");
    response->setBody(m_content);
    
    return 0;
}

HttpServer详解

class HttpServer

mumber(成员变量)

// 是否长连接
bool m_isKeepalive;
// servlet
ServletDispatch::ptr m_dispatch;

HttpServer(构造函数)

HttpServer::HttpServer(bool keepalive
            , sylar::IOManager* worker
            , sylar::IOManager* accept_worker)
    :TcpServer(worker, accept_worker)
    ,m_isKeepalive(keepalive) {
    m_dispatch.reset(new ServletDispatch);
}

setName(设置服务器名称)

void HttpServer::setName(const std::string& v) {
    TcpServer::setName(v);
    // 设置默认servlet名称
    m_dispatch->setDefault(std::make_shared<NotFoundServlet>(v));
}

handleClient(与客户端通信)

void HttpServer::handleClient(Socket::ptr client) {
    sylar::http::HttpSession::ptr session(new HttpSession(client));
    do {
        // 接收请求报文
        auto req = session->recvRequest();
        if (!req) {
            SYLAR_LOG_WARN(g_logger) << "recv http request fail, errno = "
                << errno << " errstr = " << strerror(errno)
                << " cliet: " << *client;
            break;
        }
        // 创建响应报文
        HttpResponse::ptr rsp(new HttpResponse(req->getVersion()
                                , req->isClosed() || !m_isKeepalive));
		
        // 设置Server名Head
        rsp->setHeader("Server", getName());
        // 执行操作
        m_dispatch->handle(req, rsp, session);
        // 发送响应报文
        session->sendResponse(rsp);
		
        // 若不支持长连接,关闭
        if (!m_isKeepalive || req->isClosed()) {
            break;
        }
    } while (true);
    // 关闭socket
    session->close();
}