简体   繁体   中英

Not accepting when handling async_accept?

I am trying to learn ASIO boost but I am having a hard time understanding it. I'd like to make a base layout for a server that should be scalable and performant.

In the following URL there is an example where a small TCP server is setup: http://www.boost.org/doc/libs/1_42_0/doc/html/boost_asio/tutorial/tutdaytime3/src.html

What I don't understand is the following part:

void start_accept()
{
tcp_connection::pointer new_connection =
  tcp_connection::create(acceptor_.io_service());

acceptor_.async_accept(new_connection->socket(),
    boost::bind(&tcp_server::handle_accept, this, new_connection,
      boost::asio::placeholders::error));
}

void handle_accept(tcp_connection::pointer new_connection,
  const boost::system::error_code& error)
{
   if (!error)
   {
     new_connection->start();
     start_accept();
   }
}

start_accept() eventually calls async_accept() which calls it's handler when it receives data. And the handler calls start_accept() when being done.

But what would happen if a client would try to connect when the handler would still be running? Isn't it true that the request couldn't be handled because async_accept() wasn't listening anymore?

I hope you can point me in a right direction if I am seeing things in a wrong perspective.

I reckon you noticed that the handler posts a new async_accept operation immediately after handling the accept ( new_connection->start() ):

void handle_accept(tcp_connection::pointer new_connection,
  const boost::system::error_code& error)
{
   if (!error)
   {
     new_connection->start();   // this posts connection specific asynch operations
     start_accept();            // THIS POSTS THE ASYNC OPERATION AGAIN
   }
}

You ask whether there is a race condition there (where the new async accept is not pending at the exact moment a connection is received by the kernel).

There is no such race, since the kernel queues the events in the TCP/IP stack implementation.


As a matter of fact, look at the traditional select / poll / epoll approaches, similarly, you don't get an asynchronous signal when a socket changes state. Instead you can poll for it at your own leisure.

The kernel will have some limits on time, buffer size and number on the pending events, so if you fail to handle the events for a certain time, they might be gone.

As long as userland code doesn't have direct control over raw hardware, there will never be a race condition there, since the OS stack will have to abstract the lowlevel interrupt requests away (otherwise you'd call that OS an ExoKernel ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM