0

我正在使用 Boost asio 打开几个套接字我使用一个集合,该集合具有指向具有所有套接字信息的自定义类的共享指针。这个类也有这样的handle_read功能,async_receive因为我需要对每个接收做不同的事情,我不能绑定额外的参数。

我遇到的问题是,当我关闭套接字时,我删除了对该指针的最后一个引用,因此在handle_read没有任何有效引用的情况下调用该函数,然后代码就中断了。

void SocketsAPI::do_close(const SocketInfo socket)
{
    log("do_close");
    if (!socket.m_socket || !socket.m_socket->is_open()) {
        return;
    }   
    boost::system::error_code errorcode;
    socket.m_socket->shutdown(boost::asio::ip::tcp::socket::shutdown_both, errorcode);
    if (errorcode) {
        trace("Closing failed: ", errorcode.message());
    }
    socket.m_socket->close(errorcode);
    if (errorcode) {
        trace("Closing2 failed: ", errorcode.message());
    }
    mapType::iterator iter = sockets.find(socket.key);
    if (iter != sockets.end()) {
        sockets.erase (iter);
    }
    log("do_close end");
}

事实上,我不希望handle_read调用该函数,但我无法避免它,而且在多线程实现(多个线程调用io_service.run())中更糟糕的是,handle_read将在关闭仍在处理时调用,因此“this”对象将在处理程序的任何点被释放。

4

1 回答 1

2

听起来您很接近,但还不太了解通常使用 Boost.Asio 异步方法在应用程序中完成的共享所有权语义。您需要shared_from_this()绑定回调处理程序时使用,以确保它们在异步操作期间保持在范围内。io_service::~io_service()文档很好地解释了这一点

当您需要提前停止异步操作时,请取消它SocketsAPI::do_close()而不是在您的方法中关闭套接字。然后您的回调将获得一个错误代码boost::asio::error::operation_aborted,您可以使用该代码做出适当的反应。


handle_read在关闭仍在处理时调用,因此“this”对象将在处理程序的任何点被释放。

这确实是一个单独的问题,您需要使用strands 来确保在处理程序回调中独占访问数据结构。

于 2013-03-15T18:39:30.693 回答