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
相关产品推荐
相关产品推荐

