发布关闭Boost Asio Acceptor

时间:2014-03-31 08:33:01

标签: c++ multithreading boost boost-asio tcpserver

我正在尝试关闭asio ip :: tcp :: acceptor。以下是我正在使用的代码(松散地基于async server example)来启动和运行tcp侦听器/服务器:

启动服务:

bool TCPServer::listen()
{
    try
    {
        if(std::atoi(_port.c_str()) <= 0)
        {
            LOG_ERROR("Configured port is invalid. Application will not work. Please check config file.");
            return false;
        }

        int noOfThreads = 5;

        using namespace boost::asio::ip;

        tcp::endpoint endpoint(address::from_string(_host), std::atoi(_port.c_str()));
        _acceptor.reset(new tcp::acceptor(_ioService, endpoint));

        startAccept();

        for(std::size_t i = 0; i < static_cast<unsigned>(noOfThreads); ++i)
        {
            _threads.push_back(std::thread(std::bind(static_cast<size_t (boost::asio::io_service::*)()>
                (&boost::asio::io_service::run), &_ioService)));
        }

        return true;
    }
    catch(std::exception& e)
    {
        LOG_ERROR("Received exception while trying to listen at the specified address. Please verify the address"
            << " is accurate. Exception:" << e.what());
        return false;
    }
}

以下是上面代码中调用的startAccept()函数。它启动类“TCPConnection”的对象并将其排队到asio队列。:

void TCPServer::startAccept()
{
    TCPConnection::Ptr newConn(new TCPConnection(_acceptor->get_io_service(), _processDataFn));

    _acceptor->async_accept(newConn->socket(), std::bind(&TCPServer::handleAccept, this, newConn, std::placeholders::_1));
}

以下是startAccept()函数中指定的asio异步调用的handleAccept()函数:

void TCPServer::handleAccept(TCPConnection::Ptr newConn_, const boost::system::error_code& error_)
{
    if (!error_)
    {
        newConn_->start();
    }
    else
    {
        LOG_ERROR("Encountered error while trying to accept connection. Error Code:" << error_);
    }
    startAccept();
}

上面的代码似乎运行正常并且听得很好。我面临的问题是关闭服务器。我使用以下代码关闭服务器。

TCPServer::~TCPServer()
{
    try
    {
        if(!_ioService.stopped())
        {
            _ioService.stop();
        }

        if(_acceptor)
        {
            boost::system::error_code ec;
            _acceptor->cancel(ec);
            _acceptor->close(ec);
        }

        for(std::size_t i = 0; i < _threads.size(); ++i)
        {
            if(_threads[i].joinable())
            {
                _threads[i].join();
            }
        }

        //_acceptor.reset(); // Hacky and causes memory leak.

    }
    catch(std::exception& e_)
    {
        LOG_ERROR("Received exception while shutting down listener. Exception:" << e_.what());
    }
}

问题在于,在上面的代码中,如果注释行没有取消注释,则调用此函数的线程不会返回。如果注释行被取消注释,则会导致内存泄漏(泄漏的项目是acceptor的成员变量)。请注意,该应用程序是一个简单的GUI应用程序(我使用的是wxWidgets)。上面的listen()函数和析构函数是在各种事件中从其gui线程调用的(我不确定它是否相关。但是以防万一......)。我一直在努力奋斗几个小时。任何帮助表示赞赏。

0 个答案:

没有答案