我对io_services对象的工作机制感到困惑。我的理解是有一个队列与io_service对象关联,如果任何异步调用将在队列中添加一个项目,当调用io_service.run_once时,将运行一个异步调用并从队列中出队。如果队列为空,则在添加新调用之前,io_service.run_one将不执行任何操作。我在boost示例中组织了一些代码,但似乎我的理解是错误的。
#include <boost/asio/connect.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/system/system_error.hpp>
#include <boost/asio/write.hpp>
#include <cstdlib>
#include <iostream>
#include <string>
#include <boost/bind.hpp>
using boost::asio::deadline_timer;
using boost::asio::ip::tcp;
class client
{
public:
client()
: socket_(io_service_)
{
}
void connect_handler(const boost::system::error_code& error,boost::system::error_code *er)
{
std::cerr<<"connect handler"<<std::endl;
*er = error;
std::cerr<<error<<std::endl;
}
void connect(const std::string& host, const std::string& service)
{
tcp::resolver::query query(host, service);
tcp::resolver::iterator iter = tcp::resolver(io_service_).resolve(query);
std::cerr<<"connect start"<<std::endl;
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_connect(socket_, iter, bind(&client::connect_handler,this,_1,&ec));
do
{io_service_.run_one();
}while (ec == boost::asio::error::would_block);
//io_service_.reset(); // The write async will be stuck without this reset call.
std::cerr<<"connect done"<<std::endl;
if (ec || !socket_.is_open())
throw boost::system::system_error(
ec ? ec : boost::asio::error::operation_aborted);
}
void write_handler(const boost::system::error_code& error, std::size_t size,boost::system::error_code* er )
{
std::cerr<<"write handler "<<std::endl;
*er=error;
std::cerr<<error<<std::endl;
}
void write_line(const std::string& line)
{
std::cerr<<"write start"<<std::endl;
std::string data = line + "\n";
boost::system::error_code ec = boost::asio::error::would_block;
boost::asio::async_write(socket_, boost::asio::buffer(data), bind(&client::write_handler,this,_1,_2,&ec));
do
{
io_service_.run_one();
}while (ec == boost::asio::error::would_block);
std::cerr<<"write done";
if (ec)
throw boost::system::system_error(ec);
}
private:
boost::asio::io_service io_service_;
tcp::socket socket_;
};
int main()
{
try
{
client c,d;
c.connect("172.217.6.36", "80");// google IP.
c.write_line("example");
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
我的理解是:
Start
|
async_connect ----> add one item in io_service queue
|
|
io_serivce.run_one() ------> dequeue the async_connect call back from io_serivce queue
|
|
connect_handler --------> connect_handler called change the ec value
|
|
async_write ----------> add one item in io_service queue.
|
|
io_service.run_one()------------>dequeue the async_write call back from io_serivce queue
|
|
write_handler()----------------->write handler called and change the ec value
|
Done
但现实是
Start
|
async_connect ----> add one item in io_service queue
|
|
io_serivce.run_one() ------> dequeue the async_connect call back from io_serivce queue
|
|
connect_handler --------> connect_handler called change the ec value
|
|
async_write ----------> add one item in io_service queue.
|
|
io_service.run_one()------------>stuck here in the while loop forever, the async_write handler is never be called the ec is never be changed.
Start
|
async_connect ----> add one item in io_service queue
|
|
io_serivce.run_one() ------> dequeue the async_connect call back from io_serivce queue
|
|
connect_handler --------> connect_handler called change the ec value
|
|
io_service.reset() --------> reset the io service.
|
|
async_write ----------> add one item in io_service queue.
|
|
io_service.run_one()------------>dequeue the async_write call back from io_serivce queue
|
|
write_handler()----------------->write handler called and change the ec value
|
Done
答案 0 :(得分:1)
原始样本使用截止时间计时器,该计时器位于async_waits
的连续链中。这意味着io_service
永远不会失去工作。
就是这样。整个区别。如果您让服务失效,run_*
将会返回,您需要先致电reset()
,然后才能再次使用io_service
。
另见Why must io_service::reset() be called?
对于上下文中的早期答案boost socket example stuck in while loop,我提供了几种更好的方法来使用同步调用或使用异步调用。