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

使用Boost库开发TCP异步类能否单次建立连接后多次读写

问题解答

核心可行性说明

  • 完全不需要每次读写都调用异步连接函数:TCP是面向连接的传输协议,只要套接字未主动关闭、网络没有异常断开(比如对端主动关闭、网络链路中断),仅需建立一次连接就可以在连接生命周期内发起任意多次读写操作,你提到的方案是完全可行的。
  • 实现过程需要注意几个核心约束:
    • io_context的生命周期要和套接字生命周期匹配,不能在套接字仍有异步操作待处理时提前销毁或停止io_context
    • 多线程场景下调用读写接口需要加strand调度,避免多线程同时操作同一个套接字触发未定义行为
    • 要做好错误处理,一旦连接断开需要重置套接字状态,按需添加重连逻辑即可恢复复用能力

代码示例

异步TCP客户端类实现

#include <boost/asio.hpp>
#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include <chrono>

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

class AsyncTcpClient : public std::enable_shared_from_this<AsyncTcpClient> {
public:
    AsyncTcpClient(boost::asio::io_context& io) : io_context_(io), socket_(io), strand_(io) {}

    // 连接函数,仅需调用一次即可
    void Connect(const std::string& host, const std::string& port) {
        tcp::resolver resolver(io_context_);
        auto endpoints = resolver.resolve(host, port);
        boost::asio::async_connect(socket_, endpoints,
            boost::asio::bind_executor(strand_,
            [self = shared_from_this()](boost::system::error_code ec, tcp::endpoint) {
                if (!ec) {
                    std::cout << "连接建立成功" << std::endl;
                    self->connected_ = true;
                } else {
                    std::cerr << "连接失败: " << ec.message() << std::endl;
                    self->connected_ = false;
                }
            }));
    }

    // 任意位置可调用的异步读接口,示例为按换行符读取,可按需修改读取逻辑
    void Read(std::function<void(std::string, boost::system::error_code)> callback) {
        if (!connected_) {
            callback("", boost::system::errc::make_error_code(boost::system::errc::not_connected));
            return;
        }
        auto read_buf = std::make_shared<boost::asio::streambuf>();
        boost::asio::async_read_until(socket_, *read_buf, '\n',
            boost::asio::bind_executor(strand_,
            [self = shared_from_this(), read_buf, callback](boost::system::error_code ec, std::size_t bytes_transferred) {
                if (!ec) {
                    std::string data(boost::asio::buffers_begin(read_buf->data()), bytes_transferred);
                    callback(data, ec);
                } else {
                    self->connected_ = false;
                    callback("", ec);
                }
            }));
    }

    // 任意位置可调用的异步写接口
    void Write(const std::string& data, std::function<void(boost::system::error_code)> callback) {
        if (!connected_) {
            callback(boost::system::errc::make_error_code(boost::system::errc::not_connected));
            return;
        }
        auto write_buf = std::make_shared<std::string>(data + "\n");
        boost::asio::async_write(socket_, boost::asio::buffer(*write_buf),
            boost::asio::bind_executor(strand_,
            [self = shared_from_this(), write_buf, callback](boost::system::error_code ec, std::size_t) {
                if (ec) {
                    self->connected_ = false;
                }
                callback(ec);
            }));
    }

    bool IsConnected() const { return connected_; }

private:
    boost::asio::io_context& io_context_;
    tcp::socket socket_;
    boost::asio::strand<boost::asio::io_context::executor_type> strand_;
    bool connected_ = false;
};

使用示例

int main() {
    try {
        boost::asio::io_context io_context;
        auto client = std::make_shared<AsyncTcpClient>(io_context);
        // 仅调用一次连接
        client->Connect("127.0.0.1", "8080");

        // 模拟不同时机调用读写:2秒后发起读请求
        boost::asio::steady_timer read_timer(io_context, std::chrono::seconds(2));
        read_timer.async_wait([client](boost::system::error_code) {
            if (client->IsConnected()) {
                client->Read([](std::string data, boost::system::error_code ec) {
                    if (!ec) {
                        std::cout << "读取到数据: " << data;
                    }
                });
            }
        });

        // 模拟不同时机调用读写:3秒后发起写请求
        boost::asio::steady_timer write_timer(io_context, std::chrono::seconds(3));
        write_timer.async_wait([client](boost::system::error_code) {
            if (client->IsConnected()) {
                client->Write("test message", [](boost::system::error_code ec) {
                    if (!ec) {
                        std::cout << "写入成功" << std::endl;
                    }
                });
            }
        });

        io_context.run();
    } catch (std::exception& e) {
        std::cerr << "异常: " << e.what() << std::endl;
    }
    return 0;
}

注意事项

  • 示例中所有异步操作都通过strand调度,单线程跑io_context可以省略strand,保留可直接使用多线程场景下必须保留避免未定义行为
  • 读逻辑可根据业务需求替换为固定长度读取、自定义协议头+包体读取等逻辑
  • 读写发生错误时会标记连接状态置为断开,可按需扩展重连逻辑恢复复用套接字
  • 不要在异步回调中执行长时间阻塞操作,避免卡住io_context的事件循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 01:15:05