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

为何socket已接收数据,async_read_some()操作仍未执行?

问题排查与修复

你的代码里有几个关键问题,直接导致async_read_some的完成处理程序触发不了,连阻塞read()都读不到数据:

1. reading变量的逻辑完全错误

你用一个全局的reading布尔值控制读操作发起,第一个socket设置完异步读之后,reading就变成true,后面的循环根本不会再进入读操作的分支。就算某次读操作完成后把reading改回false,也只会给第一个socket重新发读请求,其他连接永远没机会触发读。这直接导致大部分连接的读操作根本没被发起,自然收不到数据。

2. 滥用io_context.restart()

每次poll()之后就调用restart()完全没必要,甚至是破坏性的。restart()只有在io_context彻底停止(比如run()跑完所有操作返回)的时候才需要用,用来重置状态以便再次运行。而poll()只是处理当前就绪的事件,之后io_context仍处于活跃状态,此时调用restart()会清空内部的异步操作状态,就算数据到达,io_context也不知道要触发对应的处理程序。

3. 所有连接共享同一个缓冲区

所有socket的读操作都用同一个message_buffer,就算读操作能触发,多个连接同时读的时候数据也会互相覆盖,结果全是乱的。

4. 仅支持单个连接

acceptingCounter设为1之后就不再发起新的async_accept,服务器只能接收一个客户端连接,这虽然不是当前读数据的直接问题,但也是明显的设计缺陷。

修复后的代码

#include <iostream>
#include <array>
#include <vector>
#include <memory>
#include <algorithm>
#include <boost/asio.hpp>

using tcp = boost::asio::ip::tcp;

int main(int argc, char *argv[])
{
    boost::asio::io_context io_context;
    tcp::acceptor acceptor(io_context, tcp::endpoint(tcp::v4(), 1025));

    std::vector<std::shared_ptr<tcp::socket>> active_sockets;

    // 递归发起异步接受,实现循环监听
    auto do_accept = [&]() {
        auto sock = std::make_shared<tcp::socket>(io_context);
        acceptor.async_accept(*sock, [&, sock](boost::system::error_code ec) {
            if (!ec) {
                std::cout << "客户端连接:" << sock->remote_endpoint() << std::endl;
                active_sockets.push_back(sock);
                
                // 为每个连接分配独立缓冲区,避免数据冲突
                auto buffer = std::make_shared<std::array<char, 2048>>();
                // 定义读操作的回调,读完自动续读
                auto do_read = [&, sock, buffer](boost::system::error_code ec, std::size_t bytes_read) {
                    if (!ec) {
                        // 处理读到的数据,这里简单打印
                        std::cout << "收到数据:" << std::string(buffer->data(), bytes_read) << std::endl;
                        // 读完继续监听下一次数据
                        sock->async_read_some(boost::asio::buffer(*buffer), do_read);
                    } else {
                        // 连接断开或出错,从列表移除
                        auto it = std::find(active_sockets.begin(), active_sockets.end(), sock);
                        if (it != active_sockets.end()) {
                            active_sockets.erase(it);
                        }
                        std::cout << "连接关闭:" << ec.message() << std::endl;
                    }
                };
                // 发起第一次读操作
                sock->async_read_some(boost::asio::buffer(*buffer), do_read);
            }
            // 不管这次接受成功与否,继续接受下一个连接
            do_accept();
        });
    };

    std::cout << "等待连接..." << std::endl;
    do_accept();

    // 让io_context持续运行处理异步事件
    io_context.run();

    return 0;
}

修复要点

  • 用std::shared_ptr管理socket和缓冲区,既避免内存泄漏,又保证异步回调中对象不会提前销毁。
  • 循环接受连接:每次异步接受完成后立刻发起下一次,支持多个客户端同时连接。
  • 每个连接用独立的缓冲区,彻底解决数据覆盖问题。
  • 读操作完成后自动发起新的异步读,保持对客户端数据的持续监听。
  • 用io_context.run()替代你原来的循环poll()+restart(),让Boost.Asio自己管理异步事件的生命周期,这才是正确的用法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 15:54:54