C++ boost::bind with std::shared_ptr trowing operation canceled on timeout handler

你说的曾经没有我的故事 提交于 2019-12-12 04:19:21

问题


I´m trying to build an asynchronous server using boost::asio.

The server is read only and needs to have a session timeout: If a session passes more than N seconds without receiving data, the session is disconnected and the client needs to start the connection again.

SocketServer.hpp

class SocketServer {

    public:
        SocketServer(boost::asio::io_service& service);
        virtual ~SocketServer();
        void StartAsync(int port);
        void StopAsync();

    private:
        void StartAccept();
        void HandleAccept(std::shared_ptr<SocketSession> session, const boost::system::error_code& errorCode);

        boost::asio::io_service &ioService;
        boost::asio::ip::tcp::acceptor acceptor;
};

SocketServer.cpp

SocketServer::SocketServer(boost::asio::io_service& service) :
                    ioService(service),
                    acceptor(service) {}

SocketServer::~SocketServer() {}

void SocketServer::StartAsync(int port)
{
    boost::asio::ip::tcp::endpoint ep(boost::asio::ip::tcp::v4(), port);

    acceptor.open(ep.protocol());
    acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    acceptor.bind(ep);

    StartAccept();
}

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

void SocketServer::StartAccept()
{
    std::shared_ptr<SocketSession> session = std::shared_ptr<SocketSession>(new SocketSession(ioService));
    acceptor.listen();
    acceptor.async_accept(session->getSessionSocket(), boost::bind(&SocketServer::HandleAccept, this, session, boost::asio::placeholders::error));
}

void SocketServer::HandleAccept(std::shared_ptr<SocketSession> session, const boost::system::error_code& errorCode)
{
    std::stringstream ss;

    if (errorCode)
    {
        std::cout << "Error accepting incoming connection: Error: " << boost::system::system_error(errorCode).what();
    }
    else
    {
        ss << "Connection accepted from address " << socket.remote_endpoint().address().to_string() << ".";
        session->start();
    }

    StartAccept();
}

SocketSession.hpp

#define MAX_BUFFER_LENGTH 1024

class SocketSession {

    public:
        SocketSession(boost::asio::io_service& service);
        virtual ~SocketSession();

        void start();
        void startTimeoutHandler();
        void HandleRead(size_t bytesTransferred, const boost::system::error_code& errorCode);
        boost::asio::ip::tcp::socket& getSessionSocket();

    private:
        boost::asio::ip::tcp::socket sessionSocket;
        char readBuffer[MAX_BUFFER_LENGTH];
        boost::asio::deadline_timer readTimeout;
        void TimeoutHandler(const boost::system::error_code& errorCode);
};

SocketSession.cpp

SocketSession::SocketSession(boost::asio::io_service& service) :
    sessionSocket(service),
    readTimeout(service) {}

SocketSession::~SocketSession() {}

void SocketSession::start()
{
    startTimeoutHandler();
    sessionSocket.async_read_some(boost::asio::buffer(readBuffer, MAX_BUFFER_LENGTH), boost::bind(&SocketSession::HandleRead, this, boost::asio::placeholders::bytes_transferred, boost::asio::placeholders::error));
}

void SocketSession::startTimeoutHandler()
{
    readTimeout.expires_from_now(boost::posix_time::seconds(10));
    readTimeout.async_wait(boost::bind(&SocketSession::TimeoutHandler, this, boost::asio::placeholders::error));
}

void SocketSession::HandleRead(size_t bytesTransferred, const boost::system::error_code& errorCode)
{
    std::stringstream ss;

    readTimeout.expires_from_now(boost::posix_time::seconds(10));

    if (errorCode)
    {
        std::cout << "Error reading data for session: Error: " << boost::system::system_error(errorCode).what();
        delete this;
    }
    else
    {
        std::string data(readBuffer, bytesTransferred);
        std::cout << "Data read:" << data << std::endl;
    }

    start();
}

{
    return sessionSocket;
}

void SocketSession::TimeoutHandler(const boost::system::error_code& errorCode)
{
    delete this;
}

This compiles fine,

My problem here is the session returns the following error once it is loaded: Error: Operation canceled at the SocketSession::HandleRead.

It seens that boost::bind doesn´t like my std::shared_ptr. I tried a version changing it to normal pointers and the server works fine.

So, here goes my questions:

Is it possible to work on boost::bind with std::shared_ptr ?

If yes, am I doing that in the correct way ?

What may be causing my code to exit without listening to the client ?

来源:https://stackoverflow.com/questions/34019004/c-boostbind-with-stdshared-ptr-trowing-operation-canceled-on-timeout-handl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!