The error is occurring in an operation on sock, not acceptor. Thus, acceptor's state should not be affected. It just requires initiating an async_accept operation with sock being in its initial closed state.
Here is a complete basic example that listens on port 12345:
std::cout << "accepting connection" << std::endl;
// Verify socket is in a closed state.
// On success or failure, acceptor will open() socket_.
void handle_accept(const boost::system::error_code& error)
// On error, return early.
std::cout << "handle_accept: " << error.message() << std::endl;
// Start reading from socket.
std::cout << "reading from socket" << std::endl;
void handle_read(const boost::system::error_code& error,
// On error, go back to listening for a new connection.
std::cout << "handle_read: " << error.message() << std::endl;
// Output read data.
// Read data, so read some more.
boost::array<char, 1024> buffer_;
When using it, I ran it in one terminal, and connected to port 12345, send messages, killed connection, then reestablished a connection. The server console output was as follows:
and the client console:
One behavioral detail of which to be aware is that although an async_accept operation may not be pending on the acceptor_, connections are still being queued. Thus, if a connection has already been accepted, and another client tries to connect, then the latter client will have its connection pending to be accepted. If this is not the desired behavior, then the acceptor needs to transition out of a listening state via close(). This answer diagrams state transitions and describes some of the acceptor behavior in more detail.