在服务器编程领域,Boost库是一个功能强大且广泛使用的工具集,它提供了多种组件,用于构建高效的网络应用,包括HTTP服务器,以下将详细介绍如何使用Boost库中的Boost.Asio和Boost.Beast组件来定义一个HTTP服务器:
1、Boost库
Boost库简介:Boost库是一个开源的C++库集合,包含超过160个库,涵盖了字符串处理、容器、迭代器、算法、模板元编程等多个领域,它由C++标准委员会成员发起,并且许多Boost库组件已经成为C++标准库的一部分。
Boost.Asio简介:Boost.Asio是Boost库中的一个跨平台的C++库,用于网络和底层I/O编程,它支持同步和异步操作,能够处理TCP、UDP、串口通信等,Boost.Asio通过提供高级抽象来简化网络编程,同时保持高性能。
Boost.Beast简介:Boost.Beast是Boost库中的一个头文件库,用于简化HTTP和WebSocket协议的处理,它基于Boost.Asio,提供了高层次的API,使得编写HTTP客户端和服务器更加容易。
2、HTTP服务器的基本架构
服务器初始化:服务器初始化包括设置监听地址和端口,创建接受器(acceptor)对象,以及绑定到指定的端口上,这一步确保服务器能够接收来自客户端的连接请求。
连接管理:连接管理器负责维护所有活跃的连接,并在新的连接到达时进行处理,每个连接都由一个会话对象表示,这些会话对象通过异步操作与客户端进行通信。
请求处理:请求处理是HTTP服务器的核心功能,当接收到客户端请求时,服务器解析请求头和主体,根据请求的内容生成相应的响应,Boost.Beast提供了方便的API来处理HTTP请求和响应。
3、使用Boost.Asio实现HTTP服务器
引入必要的头文件:需要引入Boost.Asio和Boost.Beast相关的头文件,以便使用它们提供的功能。
#include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #include <boost/beast/version.hpp> #include <boost/asio.hpp> #include <boost/config.hpp> #include <cstdlib> #include <iostream> #include <memory> #include <string> #include <thread>
定义命名空间别名:为了简化代码,可以定义一些常用的命名空间别名:
namespace beast = boost::beast; // from <boost/beast.hpp> namespace http = beast::http; // from <boost/beast/http.hpp> namespace net = boost::asio; // from <boost/asio.hpp>
创建服务器类:定义一个服务器类,封装服务器的主要功能,服务器类通常包括构造函数、析构函数、启动和停止方法等。
4、服务器构造函数
初始化IO服务对象:IO服务对象用于执行异步操作,它是Boost.Asio的核心部分。
创建信号集:信号集用于捕获外部信号(如Ctrl+C),以便在收到这些信号时优雅地关闭服务器。
创建接受器:接受器用于监听指定地址和端口上的连接请求,它需要绑定到一个特定的IP地址和端口上,并设置为允许地址重用。
创建连接管理器:连接管理器用于管理所有活跃的连接,每当有新的连接到达时,连接管理器会创建一个新的会话对象来处理该连接。
创建套接字对象:套接字对象用于接收来自客户端的数据,它与接受器一起工作,通过异步操作接收数据。
创建请求处理器:请求处理器负责处理HTTP请求并生成响应,它可以解析请求头和主体,并根据请求的内容生成适当的响应。
5、启动服务器
运行IO服务:调用io_service_.run()
方法开始运行IO服务,这将阻塞当前线程,直到所有挂起的异步操作完成或服务器被停止。
捕获异常:在运行过程中,可能会抛出各种异常,需要捕获这些异常并进行适当的处理,以确保服务器能够稳定运行。
6、处理客户端连接
异步接受连接:使用acceptor_.async_accept()
方法异步接受客户端连接,当有新的连接到达时,该方法会被调用,并将新的连接传递给连接管理器进行处理。
会话管理:每个新的连接都会创建一个会话对象,会话对象负责读取客户端发送的数据,并将其传递给请求处理器进行处理,处理完成后,会话对象会生成响应并发送给客户端,然后关闭连接。
请求处理:请求处理器解析HTTP请求,并根据请求的内容生成适当的响应,可以使用Boost.Beast提供的API来简化这一过程,可以使用http::request<http::string_body>
和http::response<http::string_body>
来表示HTTP请求和响应。
7、示例代码
完整示例:以下是一个使用Boost.Asio和Boost.Beast实现简单HTTP服务器的完整示例代码。
#include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #include <boost/beast/version.hpp> #include <boost/asio.hpp> #include <boost/config.hpp> #include <cstdlib> #include <iostream> #include <memory> #include <string> #include <thread> namespace beast = boost::beast; // from <boost/beast.hpp> namespace http = beast::http; // from <boost/beast/http.hpp> namespace net = boost::asio; // from <boost/asio.hpp> using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> typedef std::shared_ptr<http::request<http::string_body>> pfunc_get; typedef std::shared_ptr<http::request<http::string_body>> pfunc_post; // 打印函数 void print_cc(const char* str) { std::cout << str << std::endl; } void print_dd(const char* str) { std::cout << "t" << str << std::endl; } // 支持的路由和对应的处理函数 map<string, pfunc_get> supported_ = { {"/aa/bb/cc", []() { return "print_cc"; }}, {"/aa/bb/dd", []() { return "print_dd"; }} }; map<string, pfunc_post> supported_post_ = { {"/aa/bb/ee", [](const string& strJson) { return "print_ee"; }}, {"/aa/bb/ff", [](const string& strJson) { return "print_ff"; }} }; class session : public std::enable_shared_from_this<session> { beast::tcp_stream stream_; beast::flat_buffer buffer_; http::request<http::string_body> req_; public: explicit session(tcp::socket socket) : stream_(std::move(socket)) {} void start() { read(); } private: void read() { auto self = shared_from_this(); http::async_read(stream_, buffer_, req_, [self](beast::error_code ec, std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); if (!ec) self->handle_request(); }); } void handle_request() { // 处理GET请求 if (req_.method() == http::verb::get && req_.target().starts_with("/aa/bb")) { auto target = req_.target().to_string(); if (supported_.find(target) != supported_.end()) { http::response<http::string_body> res{ http::status::ok, req_.version() }; res.set(http::field::server, "Boost"); res.set(http::field::content_type, "text/plain"); res.keep_alive(req_.keep_alive()); res.body() = supported_[target](); // 调用对应的处理函数 res.prepare_payload(); auto self = shared_from_this(); http::async_write(stream_, res, [self](beast::error_code ec, std::size_t) { self->stream_.socket().shutdown(tcp::socket::shutdown_send, ec); }); } else { bad_request(); } } else if (req_.method() == http::verb::post && req_.target().starts_with("/aa/bb")) { // 处理POST请求 auto target = req_.target().to_string(); if (supported_post_.find(target) != supported_post_.end()) { http::response<http::string_body> res{ http::status::ok, req_.version() }; res.set(http::field::server, "Boost"); res.set(http::field::content_type, "text/plain"); res.keep_alive(req_.keep_alive()); res.body() = supported_post_[target](req_.body()); // 调用对应的处理函数 res.prepare_payload(); auto self = shared_from_this(); http::async_write(stream_, res, [self](beast::error_code ec, std::size_t) { self->stream_.socket().shutdown(tcp::socket::shutdown_send, ec); }); } else { bad_request(); } } else { bad_request(); } } void bad_request() { auto res = std::make_shared<http::response<http::string_body>>(http::status::bad_request, req_.version()); res->set(http::field::content_type, "text/plain"); res->body() = "Unknown HTTP-method or bad Request-Target"; res->prepare_payload(); auto self = shared_from_this(); http::async_write(stream_, *res, [self](beast::error_code ec, std::size_t) { self->stream_.socket().shutdown(tcp::socket::shutdown_send, ec); }); } }; class server { net::io_context ioc_{}; tcp::acceptor acceptor_{ioc_}; tcp::socket socket_{ioc_}; connection_manager connection_manager_{}; http::request_handler request_handler_{doc_root}; public: server(net::io_context& ioc, address, const std::string& doc_root) : ioc_{}, acceptor_{address}, socket_{ioc_}, connection_manager_{}, request_handler_{doc_root} { acceptor_.add_listener([this]{ do_accept(); }); } void run() { ioc_.run(); } private: void do_accept() { acceptor_.async_accept(socket_, [this](beast::error_code ec) { if (!ec) { connection_manager_.start(std::make_shared<session>(std::move(socket_))); } }); } }; int main(int argc, char* argv[]) { try { if (argc != 4) { std::cerr << "Usage: http://IP Address " << "For IPv4, try one of these: " << " Receiver(127.0.0.1, 8080) " << " Receiver(IPv4-mapped IPv6 address) will also accept connections in IPv4 "; return EXIT_FAILURE; } auto const address = net::ip::make_address(argv[1]); short port = static_cast<short>(std::atoi(argv[2])); std::string doc_root = argv[3]; server s(ioc, address, doc_root); s.run(); } catch (std::exception const& e) { std::cerr << "Exception: " << e.what(); } }
小伙伴们,上文介绍了“服务器boostdefine”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。
原创文章,作者:K-seo,如若转载,请注明出处:https://www.kdun.cn/ask/755019.html