如何用c++实现一个简单的HTTP服务器? (基于Boost.Beast)

因为C++23的std::net尚未实现且编译器不支持,而Boost.Beast是当前最稳定、文档最全、基于Asio的HTTP库,提供语义清晰的http::request/response类型,避免手动解析。

为什么不用 std::net 而选 Boost.Beast?

因为 C++23 的 std::net 还没实装,主流编译器全不支持;Boost.Beast 是目前最稳定、文档最全、基于 Asio 的 HTTP 实现。它不封装底层 socket,但提供 http::request / http::response 等语义清晰的类型,避免手动解析状态行和 header。

最简同步 HTTP 服务器长什么样?

只响应 GET /,返回固定 HTML,无路由、无并发、不处理 POST —— 适合验证环境或嵌入式调试。关键点是:用 tcp::acceptor 监听,http::read 解析请求,http::write 发送响应,最后 socket.shutdown() 避免 FIN_WAIT2 积压。

#include 
#include 
#include 
#include 
#include 
#include 

namespace http = boost::beast::http;
namespace net = boost::asio;
using tcp = net::ip::tcp;

int main() {
    net::io_context ioc;
    tcp::acceptor acceptor{ioc, {tcp::v4(), 8080}};
    
    while (true) {
        tcp::socket socket{ioc};
        acceptor.accept(socket);
        
        boost::beast::flat_buffer buffer;
        http::request req;
        http::read(socket, buffer, req);
        
        http::response res{http::status::ok, req.version()};
        res.set(http::field::server, "Boost.Beast");
        res.set(http::field::content_type, "text/html");
        res.body() = "

Hello from Beast

"; res.prepare_payload(); http::write(socket, res); socket.shutdown(tcp::socket::shutdown_send); } }

常见崩溃点:忘记 prepare_payload() 或漏掉 shutdown

不调用 res.prepare_payload()Content-Length 不会自动计算,浏览器可能卡住等待 body;不调用 socket.shutdown(),连接停留在 CLOSE_WAIT,Linux 下很快耗尽文件描述符。另外:http::read 默认只读一次,遇到分块传输或大请求会截断 —— 生产环境必须用 http::parser 并循环 parse

  • http::read 是阻塞式,别在高并发场景直接用
  • 响应体超过几 KB 时,flat_buffer 默认 512 字节不够,需传入更大 buffer
  • Windows 上监听 INADDR_ANY 可能被防火墙拦截,建议显式 bind tcp::v4()

想加 HTTPS?别硬改 Beast

Beast 本身不处理 TLS 握手,得套一层 ssl::stream<:socket>。但证书加载、SNI、ALPN 协商逻辑复杂,容易配错导致 handshake_failed。更稳妥的做法是前端挂 nginx 做反向代理,或直接换用 cpp-httplib(内置 OpenSSL 封装)—— Beast 的优势在协议层控制力,不在开箱即用。