Reputation: 15
I'm writing a small client class that uses boost asio to connect to a remote socket. It should be able to try to reconnect if the initial connection failed.
When testing for that scenario, i.e. there is no open remote socket, the completion handler of async_connect got called correctly the first time. But my completion handler will never be called again for the second attempt when m_state goes into State_Connect again. What am I doing wrong?
class Test
{
public:
Test() : m_socket(m_io)
{
}
void update()
{
switch (m_state)
{
case State_Connect:
std::cout << "Start connect\n";
m_socket.async_connect(tcp::endpoint(tcp::v4(), 33000),
boost::bind(&Test::onCompleted, this, asio::placeholders::error));
m_state = State_Connecting;
break;
case State_Connecting:
if (m_error)
{
m_error.clear();
std::cout << "Could not connect\n";
m_state = State_Connect;
}
break;
}
m_io.poll_one();
}
private:
void onCompleted(const bs::error_code& error)
{
if (error)
{
m_error = error;
m_socket.close();
}
}
enum State
{
State_Connect,
State_Connecting,
};
State m_state = State_Connect;
asio::io_service m_io;
tcp::socket m_socket;
bs::error_code m_error;
};
int main(int argc, char* argv[])
{
Test test;
for (;;)
{
test.update();
boost::this_thread::sleep(boost::posix_time::milliseconds(20));
}
return 0;
}
Output is: Start connect Could not connect Start connect
But I expect it to repeat indefinitely.
Upvotes: 1
Views: 781
Reputation: 20936
When an io_context object is stopped, calls to run(), run_one(), poll() or poll_one() will return immediately without invoking any handlers.
When you call poll_one()
and no handler is ready, poll_one()
function marks io_service
as stopped. poll_one()
has nothing to do when m_state
is State_Connecting
and in this moment io_service is marked as stopped due to the empty queue of handlers.
You can test if io_service
is stopped, if so call reset
:
if (m_io.stopped())
m_io.reset();
m_io.poll_one();
Upvotes: 2