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

Boost Asio async_connect未触发回调的问题求助

Boost Asio TCP异步Syslog客户端回调未触发问题排查与修复

核心问题:IO服务未启动

Boost Asio的所有异步操作依赖io_service.run()(或run_one()/poll())驱动事件循环,处理完成的异步操作回调。你的main函数仅调用Sleep(5000),从未启动IO服务,导致异步连接完成后无法触发HandleConnect回调。

其他关键错误点

  • 构造函数手动调用socket.open():async_connect会自动处理socket的打开操作,手动提前打开可能导致socket状态异常,建议移除该调用。
  • HandleConnect逻辑倒置:连接成功时ec为空(!ec为真),但你在else分支才执行发送操作,逻辑完全反了,会导致连接成功时无动作、连接失败才尝试发送。
  • 构造函数参数类型不匹配:TcpConnection构造函数接受uint32_t to作为目标IP,但main中传入asio::ip::address对象,会导致编译错误,需修正参数类型。
  • 语法错误:main中auto messageStr = "syslog report"缺少分号,会导致编译失败。

修正后的完整代码

#include <boost/asio.hpp>
#include <boost/bind/bind.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <memory>
#include <string>

// 假设EKA_TRACE_ERROR和TR是已定义的日志宏
#define EKA_TRACE_ERROR() std::cerr
#define TR ""

class TcpConnection
    : public boost::enable_shared_from_this<TcpConnection>
{
public:
    TcpConnection(
        boost::asio::io_service& io_service,
        const boost::asio::ip::address& to,
        uint16_t port)    
        : m_socket(io_service)
        , m_ep(to, port)
    {
        // 移除手动open调用,async_connect会自动处理socket打开
    }

    void SendMessageAsync(const boost::asio::const_buffer& message)
    {
        m_socket.async_connect(m_ep, 
            boost::bind(&TcpConnection::HandleConnect, shared_from_this(), 
                boost::asio::placeholders::error, message));
    }
 
private:
    void HandleConnect(const boost::system::error_code& ec, const boost::asio::const_buffer& message)
    {
        if (!ec) {
            // 连接成功,执行异步发送
            m_socket.async_send(message,
                boost::bind(&TcpConnection::HandleWritten, shared_from_this(),
                    boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
        } else {
            // 连接失败,输出错误信息
            EKA_TRACE_ERROR() << TR << "Connect failed: " << ec.message() << std::endl;
        }
    }

    void HandleWritten(const boost::system::error_code& ec, size_t bytes_transferred)
    {   
        if (!ec) {
            EKA_TRACE_ERROR() << TR << "Sent " << bytes_transferred << " bytes successfully" << std::endl;
        } else {
            EKA_TRACE_ERROR() << TR << "Send failed: " << ec.message() << std::endl;
        }
    }

private:
    boost::asio::ip::tcp::socket m_socket;
    const boost::asio::ip::tcp::endpoint m_ep;
};

int main(int argc, char** argv)
{
    boost::asio::io_service io_service;
    auto connection = boost::make_shared<TcpConnection>(
         io_service, boost::asio::ip::address::from_string("10.16.82.22"), 514);

    auto messageStr = "syslog report";
    connection->SendMessageAsync(boost::asio::buffer(messageStr));
    io_service.run(); // 启动IO服务,处理异步操作回调
    return 0;
}

额外说明

  • io_service.run()会阻塞直到所有异步操作完成或被stop()终止,无需再调用Sleep。
  • 使用boost::asio::buffer(messageStr)即可直接封装字符串,无需嵌套boost::asio::buffer。
  • 通过shared_from_this()保证回调执行时TcpConnection对象仍存在,避免悬空引用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 00:16:09