1

I am having difficulty understanding the role of io_service when it comes to TCP/IP sockets. Here is my basic understanding of io_service. The io_service->run() blocks and accepts work requests (We use the io_service::work) to post or dispatch work to the io_service. Am I correct here? Please let me know if I am missing anything? Now following is my code for a simple server

void RunServer()
{
    boost::shared_ptr< boost::asio::io_service > io_service(new boost::asio::io_service);
    boost::shared_ptr< boost::asio::ip::tcp::acceptor > acceptor(new boost::asio::ip::tcp::acceptor( *io_service ));
    boost::shared_ptr< boost::asio::ip::tcp::socket > sock( new boost::asio::ip::tcp::socket( *io_service ) );

    try
    {
        boost::asio::ip::tcp::resolver resolver( *io_service );
        boost::asio::ip::tcp::resolver::query query( "127.0.0.1", boost::lexical_cast< std::string >( 7777 ));
        boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve( query );
        acceptor->open( endpoint.protocol() );
        acceptor->set_option( boost::asio::ip::tcp::acceptor::reuse_address( false ) );
        acceptor->bind( endpoint );
        acceptor->listen( boost::asio::socket_base::max_connections );
        acceptor->async_accept( *sock, boost::bind( OnAccept, _1, sock ) );//Receives only one connection
        std::cout << "Waiting for incoming connections \n";
        io_service->run();  //Confusion here --- Line A
    }
    catch( std::exception & ex )
    {
        std::cout << "[" << boost::this_thread::get_id()<< "] Exception: " << ex.what() << std::endl;   
    }
}

Now I know that incase there is no work object attached to io_service the method io_service->run() will never block, correct? Now my question here is what role does io_service->run() play above. From experimentation I realized that if I remove the code the OnAccept method is not called. Also where is the work being added to the io_service here. What exactly is happening here? Any explanation that clarifies this would be appreciated.

Sam Miller
  • 23,808
  • 4
  • 67
  • 87
MistyD
  • 16,373
  • 40
  • 138
  • 240
  • 1
    The "work" added to the io_service is the acceptor: you create it by passing the io_service to its constructor and when you call async_accept it posts work to the io_service. – Loghorn Mar 21 '13 at 21:57

1 Answers1

1

First of all, your simple server code looks fine. An io_service is just that, it services I/O operations. It would be useful to study the Asio anatomy to better understand its role for asynchronous operations

asynchronous connect

You do not need an io_service::work object to prevent io_service::run() from returning immediately. In your case, you have given the io_service work to do with async_accept(), and presumably more work do to in OnAccept() with another async_accept() call.

There are several other useful answers for similar questions on SO as well that you may find helpful.

Community
  • 1
  • 1
Sam Miller
  • 23,808
  • 4
  • 67
  • 87