this is my boost::asio server
class Server: public boost::enable_shared_from_this<Server>, private boost::noncopyable{
private:
boost::asio::ip::tcp::acceptor _acceptor;
boost::asio::ip::tcp::socket _socket;
public:
explicit Server(boost::asio::io_service& ios, boost::asio::ip::tcp::endpoint& endpoint):_acceptor(ios, endpoint), _socket(ios){
}
void start(){
accept();
}
void accept(){
std::cout << "accepting " << std::endl;;
_acceptor.async_accept(_socket, boost::bind(&Server::handler, this, boost::asio::placeholders::error));
}
void handler(const boost::system::error_code &ec){
const std::string message = "HTTP/1.1 200 OK\r\nContent-Length: 13\r\n\r\nHello, world!";
if(!ec){
boost::asio::async_write(_socket, boost::asio::buffer(message), boost::bind(&Server::write_handler, this));
}else{
std::cout << ec << std::endl;
}
accept();
}
void write_handler(){
}
boost::asio::ip::tcp::socket& socket(){
return _socket;
}
};
int main(){
boost::asio::io_service ios;
const unsigned int port = 5050;
boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::tcp::v4(), port);
Server server(ios, endpoint);
server.start();
ios.run();
return 0;
}
for the first time it responds with an ‘Hallo World’;
Then it just keeps looping in accept <–> handler loop and doesn’t write the welcome message. ec prints
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
asio.misc:1
accepting
......
and never stops
The infinite loop is the result of
_socketbeing in use. The firstasync_accept()works because_socketis not in use. However, the_socketis never closed, so additional calls toasync_accept()with_socketare going to fail. Theasync_accept()‘s peer argument expects that the socket is not in use, as it is going to use the socket for a new connection. This can be resolved by either:boost::shared_ptr. This allows the server to handle multiple concurrent connections._socketin thewrite_handler, then invokeaccept(). This limits the server to one connection at a time.Also, be careful with
async_write(). Ownership of the underlying buffer memory is retained by the caller, who must guarantee that it remains valid until the handler is called. In this case,messagewill pop off of the stack beforewrite_handler()is invoked. Withmessagebeingconst, consider making itstaticto guarantee its duration.Use
shared_from_this()instead ofthiswhen passing in the object to the instance to thebindcall. Otherwise, the instance pointed to bythismay be deleted, as referencing counting only properly takes place when usingshared_from_this().Finally, when printing
boost::system::error_code, use theerror_code.message()method to get a more meaningful message. In the case of the infinite loop, it would print “Already open”.Here is the modified
handler()andwrite_handler()code that supports one connection at a time: