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

Boost.Asio Daytime服务器用std::async遇问题及疑问求助

Boost.Asio Daytime 服务器改编相关问题解答

背景

我在学习Boost.Asio(版本1.84,基于C++20,运行环境Ubuntu 23.04),改编了官方的Daytime服务器示例。为模拟耗时任务,我让make_daytime_string()睡眠5秒,用std::async异步执行这个任务,之后在std::async的任务末尾通过boost::asio::post调用async_write,确保它和其他完成处理程序在同一线程执行。

问题与解答

问题1:是否必须用post?直接在std::async里调用async_write行不行?二者有啥区别?

  • 直接调用是允许的,但不推荐,不符合Asio的线程安全规范:
    • 用boost::asio::post的好处:
      1. 把async_write的启动逻辑提交到Asio的io_context线程执行,严格遵循Asio的IO对象线程安全规则——IO对象(比如socket)的操作应该在同一个strand或io_context线程中发起,避免多线程操作引发竞态问题。
      2. 所有IO相关的完成处理程序都在统一的线程上下文执行,不用额外处理跨线程同步的问题。
        缺点就是多了一次任务调度的微小开销,基本可以忽略。
    • 直接在std::async任务里调用的问题:
      std::async的线程是标准库管理的,不属于Asio的io_context线程池。直接在这线程里调用async_write,相当于在非Asio管理的线程操作IO对象,可能触发线程安全风险;而且后续的完成处理程序执行线程可能和其他Asio逻辑不在同一上下文,增加代码的复杂度。

问题2:tcp_connection析构函数不触发,客户端收不到boost::asio::error::eof,只有终止服务器时客户端才关闭

问题根源

全局的std::future持有了tcp_connection的shared_ptr,导致对象的引用计数一直没法降到0,所以析构函数不会被调用,socket也不会主动关闭,客户端自然收不到eof错误。

解决方法

用移动语义转移shared_ptr的所有权,让std::future不再持有这个对象的持久引用。异步任务完成后,shared_ptr的引用计数会正常递减,对象得以析构,socket正常关闭,客户端就能收到eof信号了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 15:00:09