调用socket.close()
不会破坏套接字。但是,应用程序可能需要管理操作和完成处理程序所依赖的对象的生命周期,但这不一定是套接字对象本身。例如,考虑一个client
类,该类包含一个缓冲区,一个套接字,并具有一个完成处理器为client::handle_read()
的完成处理。人们可以close()
并明确摧毁插座,但至少到处理程序被调用的缓冲和client
实例必须保持有效:
class client
{
...
void read()
{
// Post handler that will start a read operation.
io_service_.post([this]() {
async_read(*socket, boost::asio::buffer(buffer_);
boost::bind(&client::handle_read, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
});
}
void handle_read(
const boost::system::error_code& error,
std::size_t bytes_transferred
)
{
// make use of data members...if socket_ is not used, then it
// is safe for socket to have already been destroyed.
}
void close()
{
io_service_.post([this]() {
socket_->close();
// As long as outstanding completion handlers do not
// invoke operations on socket_, then socket_ can be
// destroyed.
socket_.release(nullptr);
});
}
private:
boost::asio::io_service& io_service_;
// Not a typical pattern, but used to exemplify that outstanding
// operations on `socket_` are not explicitly dependent on the
// lifetime of `socket_`.
std::unique_ptr<boost::asio::socket> socket_;
std::array<char, 512> buffer_;
...
}
应用程序负责管理对象的生命周期在其上运行和处理程序是依赖的。该chat client example由低保chat_client
实例被销毁后它不再使用实现了这一点,通过等待io_service.run()
的线程join()
内返回:
int main(...)
{
try
{
...
boost::asio::io_service io_service;
chat_client c(...);
std::thread t([&io_service](){ io_service.run(); });
...
c.close();
t.join(); // Wait for `io_service.run` to return, guaranteeing
// that `chat_client` is no longer in use.
} // The `chat_client` instance is destroyed.
catch (std::exception& e)
{
...
}
}
一个常见的成语是管理对象寿命使I/O对象由从enable_shared_from_this<>
继承的单个类来管理。当一个类继承自enable_shared_from_this
时,它提供了一个shared_from_this()
成员函数,该函数返回管理this
的有效shared_ptr
实例。将shared_ptr
的副本传递给完成处理程序,例如lambdas中的捕获列表或作为实例句柄传递给bind()
,从而导致I/O对象的生命周期至少与处理程序一样长。有关使用此方法的示例,请参阅Boost.Asio asynchronous TCP daytime server教程。
到您的[现已删除评论](http://stackoverflow.com/questions/35393015/how-do-you-correctly-close-sockets-in-boostasio#comment58492034_35393083)_“关闭套接字不肯定不会导致所有待处理的回调被调用时出现错误。“_:那么你会怎么说呢? – sehe