C++ boost::asio::tcp::套接字关闭并取消,而不调用处理程序

C++ boost::asio::tcp::套接字关闭并取消,而不调用处理程序,c++,boost,boost-asio,C++,Boost,Boost Asio,我正在用boost的asio库编写一个服务器。服务器使用一组连接对象(围绕boost::asio::tcp::socket的包装类)处理许多并发连接。在连接类中,使用socket.async_read_some(…)不断读取套接字,并且每当使用新数据调用读取处理程序时,都会立即再次调用socket.async_read_some()以读取更多数据 现在,服务器可能会出于某种原因决定断开客户机的连接,因此自然要做的事情是调用connection.close(),然后调用socket.close()

我正在用boost的asio库编写一个服务器。服务器使用一组连接对象(围绕boost::asio::tcp::socket的包装类)处理许多并发连接。在连接类中,使用socket.async_read_some(…)不断读取套接字,并且每当使用新数据调用读取处理程序时,都会立即再次调用socket.async_read_some()以读取更多数据

现在,服务器可能会出于某种原因决定断开客户机的连接,因此自然要做的事情是调用connection.close(),然后调用socket.close(),这将导致取消所有挂起的异步操作。这会导致读取处理程序(绑定到类连接中的方法)在boost::asio::error::operation_中止时被调用。我的问题是:我不想发生这种事

在socket.close()之后,我要销毁套接字和连接,然后从服务器的活动客户端列表中删除其指针。但是,读取处理程序在io_service.run()的下一次迭代之前不会被调用,这意味着在调用处理程序时出现错误之前,我无法立即销毁套接字或传递给socket.async_read_some()的读取处理程序。因此,我不得不以某种方式推迟对这些物体的破坏;真烦人

有没有安全的方法可以到达

  • 在不调用任何处理程序的情况下取消挂起的异步操作,这样我就可以在socket.close()之后立即安全地销毁套接字,或者
  • 安全地知道何时可能无法调用更多的处理程序

或者我的方法完全错误了吗?

当async.operation完成时(成功或出错),将调用其完成处理程序。这是重要的保证,我认为尝试“黑客”这种行为不是个好主意。
您在用例中遇到的问题通常通过使用shared_ptr来解决(shared_来自这个习惯用法):绑定
shared_ptr
到处理程序,当您中止操作(或其他一些错误)时,不要发出另一个异步读取,因此,当所有的处理程序都完成时,连接对象将与其套接字一起销毁。

这听起来很好。我肯定没有充分使用shared_ptr,甚至不知道如何从这里启用shared_。我过去经常这样做:“socket.async_connect(endpoint,boost::bind(&Connection::done_connect,this,_1)),所以现在我只需在bind调用中添加一个额外的“shared_from_this()”,并为一个额外的共享_ptr更新方法签名,即使实际的共享_ptr在处理程序中都不会使用?也就是说,共享的ptr只是为了保证对象仍然存在。听起来对吗?至少我是这样实现的,现在效果很好。多谢各位@jlh,说共享的ptr“不会在处理程序中使用”是不太正确的。如果将成员函数绑定到shared_ptr,它将存储在绑定器(使用bind()创建的函子)中,并在函子调用时取消引用。因此,指针对象的寿命与函子的寿命一样长。我想我首先并没有按照您想象的方式实现它,因为除了绑定“this”之外,我还将共享的ptr绑定到回调。(参见我的第一条评论)因此,共享的\u ptr实际上从未被使用过(除了隐式使用保持对象的活动性)。我现在修复了它,所以调用现在看起来像“socket.async_connect(endpoint,boost::bind(&Connection::done_connect,shared_from_this(),_1))”。这可能就是您的意思,现在共享的ptr在调用该方法时会被取消引用。再次感谢!