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

协程环境下复用boost::asio接收的socket遇发送无响应问题求助

Boost::Asio socket存储导致async_send无响应的解决方法

你的代码核心问题在于socket对象的移动赋值操作导致内部状态异常。在run_server协程中,你先通过std::make_shared创建了一个未打开的socket,随后用async_accept返回的已连接socket对其进行移动赋值。虽然Asio的socket支持移动语义,但这种先创建再赋值的方式可能破坏socket内部的异步操作上下文,导致后续async_send无法正常触发。

另外,std::rand()生成的handle存在重复风险,可能覆盖已有的连接,但这不是当前send无响应的直接原因。

修复方案

  1. 直接用async_accept的结果构造shared_ptr
    避免先创建空socket再赋值,直接通过async_accept返回的已连接socket初始化shared_ptr,确保socket状态从一开始就是正确的:

    修改run_server协程的关键代码:

    asio::awaitable<void> run_server(asio::io_context &context) // contex is globally allocated
    {
            asio::ip::tcp::acceptor acceptor(context, asio::ip::tcp::endpoint{asio::ip::make_address_v4(p_joinserver->get_ip_addr()), p_joinserver->get_port()});
            while (true)
            {
                // 直接用async_accept返回的socket构造shared_ptr
                auto psocket = std::make_shared<socket_t>(co_await acceptor.async_accept(asio::use_awaitable));
                auto handle = std::rand();
                // 处理handle重复,避免覆盖已有连接
                while (!p_server->connections.emplace(handle, psocket).second)
                {
                    handle = std::rand();
                }
    
                asio::co_spawn(context, read_requests(handle), asio::detached);
            }
    }
    
  2. 确保send操作的缓冲区有效
    在read_requests中,line是固定大小的字符串,每次async_read_some后,未被覆盖的旧数据会保留。建议在send前根据实际读取的字节数截取缓冲区:

    auto n_read = co_await psocket->async_read_some(
        asio::buffer(line),
        asio::use_awaitable);
    // 截取实际读取的数据
    line.resize(n_read);
    // 准备发送逻辑...
    auto n_sent = co_await _psocket->async_send(
         asio::buffer(line),
         asio::use_awaitable);
    

额外注意事项

  • 避免使用std::rand()生成唯一handle,推荐使用原子自增的整数或UUID,确保连接标识唯一。
  • 当连接关闭时,记得从connections中移除对应的shared_ptr,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Alexandre Guerchoig

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 18:15:17