The error occurs during the sock operation, not the acceptor . Therefore, the acceptor state acceptor not be affected. It just requires initiating the async_accept operation with sock in the initial closed state.
Here is a complete basic example that listens on port 12345:
#include <iostream> #include <boost/array.hpp> #include <boost/asio.hpp> using boost::asio::ip::tcp; class tcp_reader { public: tcp_reader(boost::asio::io_service& io_service) : io_service_(io_service), socket_(io_service), acceptor_(io_service, tcp::endpoint(tcp::v4(), 12345)) { accept_connection(); } private: void accept_connection() { std::cout << "accepting connection" << std::endl; // Verify socket is in a closed state. socket_.close(); // On success or failure, acceptor will open() socket_. acceptor_.async_accept(socket_, boost::bind(&tcp_reader::handle_accept, this, boost::asio::placeholders::error)); } void handle_accept(const boost::system::error_code& error) { // On error, return early. if (error) { std::cout << "handle_accept: " << error.message() << std::endl; return; } // Start reading from socket. read(); } void read() { std::cout << "reading from socket" << std::endl; async_read(socket_, boost::asio::buffer(buffer_), boost::asio::transfer_at_least(1), boost::bind(&tcp_reader::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } void handle_read(const boost::system::error_code& error, std::size_t bytes_transferred) { // On error, go back to listening for a new connection. if (error) { std::cout << "handle_read: " << error.message() << std::endl; accept_connection(); return; } // Output read data. std::cout.write(&buffer_[0], bytes_transferred); // Read data, so read some more. read(); } private: boost::asio::io_service& io_service_; tcp::socket socket_; tcp::acceptor acceptor_; boost::array<char, 1024> buffer_; }; int main() { boost::asio::io_service io_service; tcp_reader reader(io_service); io_service.run(); }
When using it, I ran it on one terminal and connected to port 12345, sent messages, killed the connection, and then restored the connection. The output from the server console was as follows:
[ twsansbury@localhost ] $ ./a.out
accepting connection
reading from socket
hello
reading from socket
goodbye
reading from socket
handle_read: End of file
accepting connection
reading from socket
oh oh no
reading from socket
handle_read: End of file
accepting connection
ctrl + c
and client console:
[ twsansbury@localhost ] $ nc 127.0.0.1 12345
hello
goodbye
ctrl + c
[ twsansbury@localhost ] $ nc 127.0.0.1 12345
oh oh no
ctrl + c
One behavioral detail to be aware of is that although the async_accept operation cannot be deferred to acceptor_ , connections are still in the queue. Thus, if the connection has already been accepted and another client is trying to connect, the last client will have its connection pending. If this is not the desired behavior, then the acceptor must transition from the listening state through close() . This response diagram displays the state of transitions and describes some of the acceptor behavior in more detail.