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

Boost.Asio递归调用start后,回调函数为何立即触发?

问题原因与解决方案

你的问题核心是streambuf未正确消费已处理数据,且未判断错误码就递归调用start(),导致回调被无限触发。

具体原因:

  • async_read_until完成后,读取到的数据会保留在buf中,但你没有调用buf.consume(bytes_transferred)移除已处理的字节。下一次调用start()时,async_read_until会直接检测到缓冲区里已有分隔符"\0",无需等待新的网络数据就立即触发回调,形成无限递归循环。
  • 未处理error_code:即使连接断开(如客户端下线),回调仍会执行并继续调用start(),导致无意义的循环。

修正后的代码:

class session : public std::enable_shared_from_this<session> {
public:
    session(tcp::socket&& socket) : socket(std::move(socket)) {}

    void start() {
        async_read_until(socket, buf, "\0", 
            [self = shared_from_this()](boost::system::error_code code, size_t bytes_transferred) {
                // 检测错误,连接异常则终止会话
                if (code) {
                    std::cout << "会话异常或关闭: " << code.message() << "\n";
                    return;
                }

                // 提取数据时剔除末尾的"\0"分隔符
                std::string require(buffer_cast<const char*>(self->buf.data()), bytes_transferred - 1);
                std::cout << "GET: " << require << "\n";

                if (require == "Hi") {
                    async_write(self->socket, buffer("Hello\0"), [](boost::system::error_code code, size_t) {
                        if (!code) {
                            std::cout << "SEND: Hello\n";
                        }
                    });
                }

                // 消费已处理的字节,清空缓冲区已用部分
                self->buf.consume(bytes_transferred);
                // 发起下一次异步读取
                self->start();
            });
    }
private:
    tcp::socket socket;
    boost::asio::streambuf buf;
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 14:47:21