You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Boost.Beast的简易HTTP服务器异常问题求助

基于Boost.Beast的HTTP服务器问题修复

问题概述

当前服务器存在两个异常:

  • 处理第二个请求时服务器关闭
  • 无法返回FileCollector缓存的文件内容

代码问题分析与修复

问题1:第二个请求导致服务器关闭

核心问题点

  1. socket引用悬空:start_acceptor参数tcp::socket& sock被复用,第一次std::move(sock)后,引用指向已失效对象,后续accept操作出错
  2. shared_ptr所有权错误转移:std::move(fc)将FileCollector的智能指针所有权转移给第一个连接,后续连接拿到空指针
  3. 强制关闭持久连接:response_.keep_alive(false)强制客户端关闭连接,且响应完成后未重启请求读取逻辑

修复后的start_acceptor代码

void ownHTTPServer::start_acceptor(tcp::acceptor& accepter, std::shared_ptr<Collector::FileCollector>& fc)
{
    // 每次accept创建新socket,避免引用悬空
    tcp::socket sock(accepter.get_executor());
    accepter.async_accept(sock,
        [&, fc](beast::error_code er){
            if (!er)
            {
                // 传递shared_ptr拷贝,确保所有连接共享同一缓存
                std::make_shared<ownHTTPServer::http_connection>(std::move(sock), fc)->start();
            }
            start_acceptor(accepter, fc);
        });
}

修复http_connection的连接逻辑(支持持久连接)

void http_connection::process_request(void)
{
    response_.version(request_.version());
    // 根据请求头决定是否保持连接,而非强制关闭
    response_.keep_alive(request_.keep_alive());

    switch (request_.method())
    {
        case http::verb::get:
            response_.result(http::status::ok);
            response_.set(http::field::server, "Beast");
            create_response();
            break;
        default:
            response_.result(http::status::bad_request);
            response_.set(http::field::content_type, "text/plain");
            beast::ostream(response_.body())
                << "Invalid request-method '"
                << std::string(request_.method_string())
                << "'";
            break;
    }
    write_response();
}

void http_connection::write_response(void)
{
    auto self = shared_from_this();
    response_.content_length(response_.body().size());
    http::async_write(
        socket_,
        response_,
        [self](beast::error_code er, std::size_t bytes_trans)
        {
            boost::ignore_unused(bytes_trans);
            if (!er && self->response_.keep_alive())
            {
                // 重置请求响应,读取下一个请求
                self->request_ = {};
                self->response_ = {};
                self->read_request();
                return;
            }
            // 关闭连接
            self->socket_.shutdown(tcp::socket::shutdown_send, er);
        }
    );
}

问题2:无法返回FileCollector缓存内容

核心问题点

  1. FileCollector的get_file_data未实现正确的文件读取与缓存逻辑
  2. create_response未处理文件不存在的情况,返回空内容

完善FileCollector实现

#include <fstream>
#include <stdexcept>

Collector::FileCollector::FileCollector() {}

std::string Collector::FileCollector::get_file_data(std::string filename)
{
    // 检查缓存
    auto it = fileData.find(filename);
    if (it != fileData.end())
    {
        return it->second;
    }

    // 读取文件
    std::ifstream file(filename, std::ios::binary | std::ios::ate);
    if (!file.is_open())
    {
        throw std::runtime_error("File not found: " + filename);
    }

    std::streamsize size = file.tellg();
    file.seekg(0, std::ios::beg);

    std::string content(size, '\0');
    if (!file.read(&content[0], size))
    {
        throw std::runtime_error("Failed to read file: " + filename);
    }

    // 存入缓存
    fileData[filename] = content;
    return content;
}

修改create_response处理异常

void http_connection::create_response(void)
{
    std::string_view sv = request_.target().substr(1);
    std::string targetfile = {sv.data(), sv.size()};
    
    try
    {
        std::string content = filecollector->get_file_data(targetfile);
        response_.set(http::field::content_type, "text/plain"); // 可根据文件后缀优化
        response_.body() = std::move(content);
    }
    catch (const std::exception& e)
    {
        response_.result(http::status::not_found);
        response_.set(http::field::content_type, "text/plain");
        beast::ostream(response_.body()) << "File not found: " << e.what();
    }
}

Boost.Asio学习内容推荐

  • 基础入门:先掌握核心概念:io_context、异步操作、回调函数、strand(线程安全)、socket类型。从同步TCP/UDP通信开始,再过渡到异步模式。
  • 核心组件:重点学习boost::asio::ip::tcp相关类(acceptor、socket),异步操作的错误处理,以及智能指针在异步回调中的使用(避免对象提前销毁)。
  • Beast结合使用:理解Boost.Beast是基于Asio的HTTP/WebSocket库,掌握HTTP请求/响应的解析与构造,异步读写流程。
  • 实战案例:参考Boost官方提供的Beast HTTP服务器/客户端示例,逐步拆解代码逻辑,理解每个步骤的作用。
  • 线程模型:学习Asio的多线程处理方式,如何用多个io_context线程提升并发性能,以及strand的使用场景。

内容的提问来源于stack exchange,提问作者Simple Boy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 04:33:12