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

Unity客户端交互时C++ Boost Ptree多人服务器出现段错误

问题描述

正在构建Node.js与C双服务器架构的多人应用,Unity客户端连接并发送用户数据后,C服务器触发段错误直接退出,无任何提示。该问题仅在Unity客户端触发,Postman测试无异常。已确认客户端发送数据正常、传输过程无问题,但C++服务器有时无法正确获取JSON请求体。

核心问题排查与修复方案

1. 异常处理逻辑错误(直接触发崩溃)

RouteRequest函数的catch块存在严重错误:

catch (const std::exception& e)
{
    throw e.what(); // 错误:抛出const char*类型,无法被std::exception捕获,直接触发未捕获异常崩溃
    std::cout << e.what() << std::endl;
    sendHttpResponse(response, 500, "text/html", e.what());
}

修复方案:
去掉错误的抛出语句,保留正常错误处理流程;若需重新抛出异常,使用throw;保留原异常类型:

catch (const std::exception& e)
{
    std::cout << e.what() << std::endl;
    sendHttpResponse(response, 500, "text/html", e.what());
    // 如需向上传递异常,使用以下语句而非throw e.what();
    // throw;
}

2. 未读取HTTP请求体(JSON数据丢失)

当前BufferToString仅读取HTTP头部(到\r\n\r\n为止),完全未处理Unity发送的JSON请求体,导致后续解析Player对象时因无效数据触发异常崩溃。

修复方案:
从HTTP头部提取Content-Length字段,根据长度读取完整请求体:

std::string BufferToString(tcp::socket& socket, std::string& route, std::string& Method) {

    boost::asio::streambuf request_buffer;
    boost::system::error_code error;

    try
    {
        // 读取HTTP头部
        boost::asio::read_until(socket, request_buffer, "\r\n\r\n", error);
        if (error) {
            throw std::runtime_error(error.message());
        }

        std::string header_data(boost::asio::buffers_begin(request_buffer.data()),
            boost::asio::buffers_end(request_buffer.data()));

        // 解析Content-Length
        size_t content_length = 0;
        size_t cl_pos = header_data.find("Content-Length: ");
        if (cl_pos != std::string::npos) {
            size_t cl_end = header_data.find("\r\n", cl_pos);
            std::string cl_str = header_data.substr(cl_pos + 16, cl_end - (cl_pos + 16));
            content_length = std::stoull(cl_str);
        }

        // 读取JSON请求体
        std::string body_data;
        if (content_length > 0) {
            body_data.resize(content_length);
            boost::asio::read(socket, boost::asio::buffer(body_data), error);
            if (error) {
                throw std::runtime_error(error.message());
            }
        }

        // 解析请求方法与路由
        size_t path_start = header_data.find(" ");
        if (path_start != std::string::npos) {
            size_t path_end = header_data.find(" ", path_start + 1);
            route = header_data.substr(path_start + 1, path_end - path_start - 1);
        } else {
            std::cout << "String error: \n" << header_data << std::endl;
        }

        Method = header_data.substr(0, header_data.find(" "));

        // 返回JSON请求体,供后续解析
        return body_data;
    }
    catch (const std::exception& ex)
    {
        std::cout << "Exception occurred: " << ex.what() << std::endl;
        return " ";
    }
}

3. 同步连接处理导致资源堆积

主函数中同步处理连接,Unity在FixedUpdate(默认0.02秒/次)高频发送请求时,会导致大量连接阻塞、资源未正确释放,触发内存错误。

修复方案:
用线程池或后台线程异步处理连接,避免阻塞主线程:

#include <thread>
#include <memory>

int main() {
    boost::asio::io_context io_context;

    std::string raw_ip_address = "0.0.0.0";
    boost::system::error_code ec;

    boost::asio::ip::address ip_address =
        boost::asio::ip::address::from_string(raw_ip_address, ec);

    if (ec.value() != 0) {
        std::cout
            << "Failed to parse the IP address. Error code = "
            << ec.value() << ". Message: " << ec.message();
        return ec.value();
    }
    tcp::endpoint tp(ip_address, 8081);

    tcp::acceptor acceptor(io_context, tp);

    Rooms MainRooms;
    std::mutex rooms_mutex; // 确保Rooms线程安全

    while (true) {
        auto socket = std::make_shared<tcp::socket>(io_context);
        acceptor.accept(*socket);

        // 后台线程处理请求,避免阻塞主线程
        std::thread([socket, &MainRooms, &rooms_mutex]() {
            std::lock_guard<std::mutex> lock(rooms_mutex);
            RouteRequest(*socket, MainRooms);
        }).detach();
    }
    return 0;
}

注:需确保Rooms类的addRoomMate方法线程安全,必要时添加互斥锁。

4. JSON解析容错与段错误调试

  • Player构造函数容错:使用成熟JSON库(如nlohmann/json)解析数据,避免手动解析出错;确保构造函数抛出的异常均为std::exception类型。
  • 段错误定位:编译时添加-g参数生成调试信息,用GDB调试:
    gdb ./your_server_executable
    run # 启动服务器
    bt # 触发崩溃后查看调用栈,定位崩溃位置
    

内容的提问来源于stack exchange,提问作者PAVAN PRASAD 2022

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 19:44:59