boost::asio::async_read 不回调我的处理函数
Posted
技术标签:
【中文标题】boost::asio::async_read 不回调我的处理函数【英文标题】:boost::asio::async_read does not callback my handler function 【发布时间】:2017-01-08 13:40:10 【问题描述】:我正在与boost::asio
合作,在客户端和服务器应用程序之间进行TCP
通信,这两个应用程序都是由我编写的。我最初是通过使用boost::asio::read
的同步数据读取来编写的。 sync_read
工作正常,只是在读取操作期间我无法这样做 socket.cancel
。这已成为一个相当大的限制,因此 我现在正在尝试将我的同步读取转换为 async_read
机制。
以下是我的同步读取机制,非常好。我读了2遍。首先获取包头,然后获取包数据,效果很好 ->
size_t Read_Data_Sync(std::vector<unsigned char> & msg_body)
//fetch the header
MyMessageHeader msg_header;
boost::system::error_code err_code;
size_t bytes_received = boost::asio::read(socket, boost::asio::buffer(&msg_header, sizeof(msg_header)), err_code);
if (bytes_received <= 0 || err_code)
return 0;
err_code.clear();
msg_body.resize(msg_header.size);
//fetch the body
bytes_received = boost::asio::read(socket, boost::asio::buffer(msg_body), err_code);
if (bytes_received <= 0 || error_code)
return 0;
return bytes_received;
上面的函数用于从客户端的thread
连续调用,我称之为阅读器线程like so
->
auto data_reader_thread = std::thread [this]
while(run_thread)
Read_Data_Sync();
;
以下是我如何更改它以使读取机制async
->
读取器线程保持不变,只是它现在调用另一个读取函数,我编写了该函数以async
方式读取数据
auto data_reader_thread = std::thread [this]
while(run_thread)
Read_Data_Async();
;
我已将msg_body
和msg_header
作为我班级的成员变量。更新后的逻辑是Read_Data_Async
是从线程函数中连续调用的。 Read_Data_Async
调用 boost::asio::async_read
绑定
Handle_Read_Header
的地址作为回调,然后再次执行 boost::asio::async_read
以读取消息体,传递处理程序回调以接收 message_body
void Read_Data_Async()
//firstly read message header
MyMessageHeader msg_header;
boost::asio::async_read(socket, boost::asio::buffer(&msg_header, sizeof(msg_header)), boost::bind(&TCPSession::Handle_Read_Header, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
void Handle_Read_Header(const boost::system::error_code & error, std::size_t bytes_transferred)
//now read the message body
if (!error && bytes_transferred > 0)
boost::asio::async_read(socket, boost::asio::buffer(msg_body), boost::bind(&TCPSession::Handle_Read_Body, this,
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
else
cout << "Error: " << error << "\n";
void Handle_Read_Body(const boost::system::error_code & error, std::size_t bytes_transferred)
if (!error && bytes_transferred > 0)
// msg_body has the data read from socket
else if (error != boost::asio::error::eof)
cout << "Error: " << error << "\n";
我现在面临的问题是回调Handle_Read_Header
永远不会被回调! 我在做什么有什么问题?我浏览了很多相关的帖子,比如this one 试图解决我的问题
问题,但该链接再次建议调用io.run
,因为它是关于boost::asio::async_read_until
而不是boost::asio::async_read
。
我的上述逻辑对boost::asio::async_read
是否正确?我应该得到什么asio
来回调我的处理函数?
【问题讨论】:
哪个线程调用io_service
对象上的run()
?
我的主线程调用io_service::run()
& io_service
在主线程上。如何使用单独的阅读器线程进行这项工作?
【参考方案1】:
您必须在某处运行 io_service::run()
¹
实际上,执行异步 IO 的整个想法是您确实不需要单独的线程来读取/写入:在单个线程上完全可以实现全双工。
¹或更复杂的循环,带有 run_one、poll 或 poll_one
【讨论】:
io_service::run()
在与服务器连接的主线程上被调用。我一定会在工作线程上调用读取,因为我的应用程序是一个不断快速更新数据的应用程序。因此我一定会有一个线程在循环中调用读取。如果没有连接,我是否也应该在我的阅读器线程中进行连接?
服务run
在没有完成处理程序时立即完成。确保在最后一个操作完成之前发布下一个操作。或使用io_service::work
。该示例显示了所有这些是如何工作的
这不是很严格吗?我是否在主线程或其他线程上调用 io_service::run()
对 asio 有什么影响?如何在工作线程上连续调用 read 来完成这项工作?应该有人遇到过同样的问题。
@SegmentationFault 我没说在哪里运行服务。真的相反。是的,很多人面临着同样的选择。从样本开始
对不起,如果我误解了。我在主线程上做io_service.run
,而我所有的读取都在一个工作线程上。这种设计不适用于async_read
?以上是关于boost::asio::async_read 不回调我的处理函数的主要内容,如果未能解决你的问题,请参考以下文章
Boost::asio::async_read 不会在条件下停止
boost::asio::async_read 无限循环,接收数据为零字节