简体   繁体   English

boost :: asio :: tcp :: socket关闭并取消,不调用处理程序

[英]boost::asio::tcp::socket Close and cancel without handlers being called

I'm writing a server with boost's asio library. 我正在用boost的asio库编写一个服务器。 The server handles many concurrent connections using a collection of Connection objects (a wrapper class around boost::asio::tcp::socket). 服务器使用一组Connection对象(boost :: asio :: tcp :: socket周围的包装类)处理许多并发连接。 Within the Connection class, the socket is constantly being read from using socket.async_read_some(...) and whenever the read handler is invoked with new data, socket.async_read_some() is immediately called again for more data to be read. 在Connection类中,不断地使用socket.async_read_some(...)读取套接字,并且每当使用新数据调用读取处理程序时,立即再次调用socket.async_read_some()以读取更多数据。

Now, the server may decide to disconnect a client for some reason, so the natural thing to do is to call connection.close() which in turn calls socket.close(), which will cause all pending async operation to be canceled. 现在,服务器可能由于某种原因决定断开客户端,因此自然要做的就是调用connection.close(),然后调用socket.close(),这将导致所有挂起的异步操作被取消。 This causes the read handler (bound to a method within class Connection) to be invoked with boost::asio::error::operation_aborted. 这会导致使用boost :: asio :: error :: operation_aborted调用读处理程序(绑定到类Connection中的方法)。 And my problem is: I don't want this to happen. 而我的问题是:我不希望这种情况发生。

After socket.close(), I'd like to destroy the socket and the connection and then remove its pointer from the server's list of active clients. 在socket.close()之后,我想销毁套接字和连接,然后从服务器的活动客户端列表中删除它的指针。 However the read handler won't be called until the next iteration of io_service.run(), which means that I cannot immediately destroy the socket or the read handler I had passed to socket.async_read_some() until the handler has been invoked with the error. 但是,在io_service.run()的下一次迭代之前不会调用读取处理程序,这意味着我无法立即销毁我已经传递给socket.async_read_some()的套接字或读取处理程序,直到调用处理程序与错误。 So I have to delay the destruction of those objects somehow; 所以我不得不以某种方式推迟对这些物体的破坏; that's annoying. 这太烦人了。

Is there a safe way to either 是否有安全的方法

  • Cancel pending async operations without any handler to be invoked, so I can safely destroy the socket immediately after socket.close(), or 取消挂起的异步操作, 不需要调用任何处理程序,所以我可以在socket.close()之后立即安全地销毁套接字,或者
  • to safely know when no more handlers can potentially be called 安全地知道什么时候不能再调用处理程序

Or am I approaching this entirely the wrong way? 还是我完全以错误的方式接近这个?

When an async.operation is complete - either successfuly or with error - its completion handler is invoked. 当async.operation完成时 - 无论是成功还是出错 - 都会调用其完成处理程序。 This is important guarantee, and I don't think it's good idea to try and "hack" this behavior. 这是重要的保证,我认为尝试“破解”这种行为并不是一个好主意。 The problem you encountered in your use-case is usually sovled by using shared_ptr (shared_from_this idiom): bind shared_ptr<Connection> to the handlers, don't issue another async_read when you get operation_aborted (or some other error), so that when all the handlers are done the Connection object is destroyed with its socket. 您在用例中遇到的问题通常是通过使用shared_ptr(shared_from_this idiom)来解决的:将shared_ptr<Connection>绑定到处理程序,当您获得operation_aborted(或其他一些错误)时不要发出另一个async_read,这样当所有处理程序完成Connection对象被其套接字销毁。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM