I am trying to learn boost asio socket. there is one interesting example in boost web page which set a deadline time to monitor the timeout and change async io to sync io fashion. but when I remove the deadline timer the program stuck in while loop in write_line, I don't understand why the connection can be setup but the socket write is stuck. it seems that the writing never finished ,the handler never called so the "ec" never changed. Thank you in advance!!
#include <boost/asio/connect.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/read_until.hpp>
#include <boost/asio/streambuf.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_),
deadline_(io_service_)
{
deadline_.expires_from_now(boost::posix_time::seconds(10));
check_deadline(); // without this line which means without the this timer
//async_wait, the code stuck in write_line io_service_.run_one() loop .
}
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);
std::cerr<<"connect done"<<std::endl; // always works fine!
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(); //stuck here without "check_deadline();" in constructor.
}while (ec == boost::asio::error::would_block);
std::cerr<<"write done";
if (ec)
throw boost::system::system_error(ec);
}
private:
void check_deadline()
{
if (deadline_.expires_at() <= deadline_timer::traits_type::now())
{
boost::system::error_code ignored_ec;
socket_.close(ignored_ec);
deadline_.expires_at(boost::posix_time::pos_infin);
throw boost::system::system_error(ignored_ec);
}
deadline_.async_wait(std::bind(&client::check_deadline, this));
}
boost::asio::io_service io_service_;
tcp::socket socket_;
deadline_timer deadline_;
};
int main()
{
try
{
client c,d;
c.connect("216.58.194.164", "80");// google IP.
c.write_line("test");
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
Without comment out line "check_deadline();" in constructor the output is :
connect start
connect handler
system:0
connect done
write start
write handler
system:0
write done
when the line "check_deadline();" comment out in constructor, the output is :
connect start
connect handler
system:0
connect done
write start
and stuck there forever.