调用socket.close()不会破坏套接字。但是,应用程序可能需要管理操作和完成处理程序所依赖的对象的生存期,但这不一定是套接字对象本身。例如,考虑一个client类,它持有一个缓冲区、一个套接字,并且有一个未完成的读操作,其完成处理程序为client::handle_read()。可以close()并显式地销毁套接字,但是至少在调用处理程序之前,buffer和client实例必须保持有效:

代码语言:javascript运行复制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 socket_;

std::array buffer_;

...

}

应用程序负责管理操作和处理程序所依赖的对象的生存期。chat client example通过在线程join()中等待io_service.run()返回来保证chat_client实例在不再使用后被销毁,从而实现了这一点

代码语言:javascript运行复制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的副本被传递给完成处理程序,比如lambda中的捕获列表,或者作为实例句柄传递给bind(),导致I/O对象的生命周期至少和处理程序一样长。有关使用此方法的示例,请参阅Boost.Asio asynchronous TCP daytime server教程。

2025-06-13 17:40:01