HTTP 框架的设计与实现

221 阅读2分钟

项目介绍

服务器开发中 Web 服务是一个基本的代码单元,将服务端的请求和响应部分的逻辑抽象出来形成框架,能够做到最高级别的框架级代码复用。本次项目将综合使用 C++11 及 Boost 中的 Asio 实现 HTTP 和 HTTPS 的服务器框架。

项目涉及的知识点

  • C++基本知识

    • 面向对象
    • 模板
    • 命名空间
    • 常用 IO 库
  • C++11 相关

    • lambda expression
    • std::shared_ptr
    • std::make_shared
    • std::unordered_map
    • std::regex
    • std::smatch
    • std::regex_match
    • std::function
    • std::thread
  • Boost Asio 相关

    • boost::asio::io_service
    • boost::asio::ip::tcp::socket
    • boost::asio::ip::tcp::v4()
    • boost::asio::ip::tcp::endpoint
    • boost::asio::ip::tcp::acceptor
    • boost::asio::streambuf
    • boost::asio::async_read
    • boost::asio::async_read_until
    • boost::asio::async_write
    • boost::asio::transfer_exactly
    • boost::asio::ssl::stream
    • boost::asio::ssl::stream_base::server
    • boost::asio::ssl::context
    • boost::asio::ssl::context::sslv23
    • boost::asio::ssl::context::pem
    • boost::system::error_code

设计前的思考

我们知道,HTTP 和 HTTPS 都是应用层的一种协议,他们的底层实际上是通过 TCP 进行传输的。因此,要实现一个 Web 框架,就必须要对浏览器访问 Web 服务器的过程做一个了解。

首先,服务端已经运行起了服务,因此在服务器启动后便开始通过 Socket 监听端口上的请求。这时,客户端浏览器想要访问服务器资源时,就会发送相应的 HTTP 或者 HTTPS 请求。当服务端收到请求后,就会处理这部分请求,返回客户端所需的资源。

仔细思考后不难发现,HTTP 和 HTTPS 两种方式的服务器之间在处理请求、返回请求唯一区别就在于他们究竟如何处理与客户端建立连接的方式上,也就是常说的 accept() 方法。

因此,我们在设计基类的时候,就可以将 accept() 方法设计成一个虚函数,留给具体的子类来实现这个方法,而真正对于服务器内部的相关逻辑,全部由基类 ServerBase 来实现。

对此,我们先确定好基类的基本设计,在ServerBase模板类中,我们只需预留一个接口start()用于启动服务器给外部调用。

由于子类需要实现虚函数 accept() 的具体方式,因此需要保留为 protected,由于我们需要对请求进行解析和应答,而这部分逻辑其实是与协议类型无关的,因此我们可以将这部分逻辑直接放到 ServerBase 中进行实现。