协程环境下复用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无响应的直接原因。
修复方案
直接用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); } }确保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
相关产品推荐
相关产品推荐

