Mendes
Mendes

Reputation: 18561

C++ Boost async server handler being called with no connection

I´m writing my first boost::asio async server and here is the code I put together:

SocketServer.hpp

    class SocketServer {

        public:
            SocketServer(boost::asio::io_service& ioService);
            virtual ~SocketServer();

            void StartAsync(int port);
            void StopAsync();

        private:
            void StartAccept();
            void HandleAccept();

            boost::asio::ip::tcp::acceptor acceptor;
            std::shared_ptr<boost::asio::ip::tcp::socket> socket;
    };

SocketServer.cpp

    SocketServer::SocketServer(boost::asio::io_service &ioService) :
        acceptor(ioService),
        socket(new boost::asio::ip::tcp::socket(ioService)) {}

    SocketServer::~SocketServer() {}

    void SocketServer::StartAsync(int port)
    {
        boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), port);
        acceptor.open(ep.protocol());
        StartAccept();
    }

    void SocketServer::StopAsync()
    {
        acceptor.cancel();
    }

    void SocketServer::StartAccept()
    {
        acceptor.async_accept(*socket, std::bind(&SocketServer::HandleAccept, this));
    }

    void SocketServer::HandleAccept()
    {

        std::cout << "Connection accepted." << std::endl;
        std::cout << "Connection accepted from " << socket->remote_endpoint().address().to_string() << std::endl;

       // Will create a new thread here to process this connection

        StartAccept();
    }

The idea is to receive multiple connection requests on the given port and open for each connection a thread to process.

The problem is that, even with no connection, the HandleAccept is being called, and the remote_endpoint throws an exception as:

remote_endpoint: Bad file desciptor

I´m a bit confused here on what´s going on.

I need to be called once for each connection, so that I can start a thread with the given connection socket.

A side question: Is that the right way of doing it, using just one socket for all connections ?

Thanks for helping.

Upvotes: 0

Views: 97

Answers (1)

Yuushi
Yuushi

Reputation: 26080

Firstly, you're missing a call to listen; this is what actually listens for incoming connections. This should be called on your acceptor before the call to async_accept:

ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), port);
acceptor.listen();
acceptor.async_accept(...);

Note that the function/function object passed to async_accept should accept a boost::system::system_error as a parameter as well:

acceptor.async_accept(
    *socket, 
    std::bind(&SocketServer::HandleAccept, this, boost::asio::placeholders::error)
);

Finally, you cannot use the same socket for multiple (simultaneous) connections.

Upvotes: 1

Related Questions