C ++ boost :: bind与std :: shared_ptr trowing操作在超时处理程序

时间:2015-12-01 11:13:58

标签: c++ asynchronous boost boost-asio

我正在尝试使用boost::asio构建异步服务器。

服务器是只读的,需要具有会话超时:如果会话超过N秒而没有 接收数据,会话断开连接,客户端需要再次启动连接。

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;
}

编译好,

我的问题是会话加载后会返回以下错误:  Error: Operation canceled上的SocketSession::HandleRead

它认为boost :: bind不像我的std::shared_ptr。我尝试了将其更改为普通指针的版本,服务器工作正常。

所以,这是我的问题:

是否可以使用boost::bind处理std::shared_ptr

如果是,我是否以正确的方式做到了?

在没有收听客户端的情况下,可能导致我的代码退出的原因是什么?

0 个答案:

没有答案