在 Boost ASIO 服务器中处理生命周期
Handling lifetime in a Boost ASIO server
我正在尝试使用 beast websockets 基本上重新创建 boost 异步日间服务器示例。
在 rubymud_server
class 的 handle_accept
方法内部调用 new_connection->handshake()
。一旦函数体退出,我相信我的 new_connection
会丢失所有引用计数并死掉。如果是这样的话,这东西返回响应是不是运气好? ws_connection
的 ws_
成员上的 ws_.async_accept
和 ws_.async_write
是否在 shared_ptr 被销毁之前完成?
class ws_connection : public boost::enable_shared_from_this<ws_connection> {
public:
typedef boost::shared_ptr<ws_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new ws_connection(io_service));
}
void handshake()
{
ws_.async_accept(boost::bind(&ws_connection::handle_accept, shared_from_this()));
}
tcp::socket& socket()
{
return ws_.next_layer();
}
private:
ws_connection(boost::asio::io_service& io_service) : ws_(io_service)
{
response_ << "Hello from obsidian-server!";
}
void handle_accept() {
ws_.async_write(response_.data(), boost::bind(&ws_connection::handle_write, shared_from_this()));
}
void handle_write() {
std::cout << "handle_write" << std::endl;
}
beast::websocket::stream<boost::asio::ip::tcp::socket> ws_;
beast::streambuf response_;
};
class rubymud_server {
public:
using error_code = boost::system::error_code;
rubymud_server(boost::asio::io_service& io_service) : acceptor_(io_service, tcp::endpoint(tcp::v4(), 33435))
{
start_accept();
}
private:
void start_accept()
{
ws_connection::pointer new_connection = ws_connection::create(acceptor_.get_io_service());
acceptor_.async_accept(new_connection->socket(),
boost::bind(
&rubymud_server::handle_accept,
this,
new_connection,
boost::asio::placeholders::error
)
);
}
void handle_accept(ws_connection::pointer new_connection, const error_code& error) {
new_connection->handshake();
start_accept();
}
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[]) {
boost::asio::io_service io_service;
rubymud_server server(io_service);
io_service.run();
}
我不确定我是否理解这个问题,但我会看看我能做些什么。我感觉你不明白io_service
是什么,所以我要说的是:io_service
是一个异步函数的队列。每个异步调用都在 io_service
的队列中。
当您构建 class 时,io_service
会传递给它。 假设 io_service
不会在 class 之前被销毁(这很重要),您的下一个要求是 class 的对象一直存活到 io_service
队列为空。为确保这一点,您 post 函数指向 io_service
,指针为 shared_from_this()
。意思是,只要 io_service
中还有一个 shared_ptr
的实例存在,你的 class 就永远不会被销毁,因为 shared_ptr
计数器永远不会为零。
再说一次:所有这些都假定 io_service
将一直存在,直到 class 的对象被销毁。一旦队列为空,this
的共享指针将自动消失,您的 shared_ptr
可以安全销毁。
这是否回答了您的问题?
我正在尝试使用 beast websockets 基本上重新创建 boost 异步日间服务器示例。
在 rubymud_server
class 的 handle_accept
方法内部调用 new_connection->handshake()
。一旦函数体退出,我相信我的 new_connection
会丢失所有引用计数并死掉。如果是这样的话,这东西返回响应是不是运气好? ws_connection
的 ws_
成员上的 ws_.async_accept
和 ws_.async_write
是否在 shared_ptr 被销毁之前完成?
class ws_connection : public boost::enable_shared_from_this<ws_connection> {
public:
typedef boost::shared_ptr<ws_connection> pointer;
static pointer create(boost::asio::io_service& io_service)
{
return pointer(new ws_connection(io_service));
}
void handshake()
{
ws_.async_accept(boost::bind(&ws_connection::handle_accept, shared_from_this()));
}
tcp::socket& socket()
{
return ws_.next_layer();
}
private:
ws_connection(boost::asio::io_service& io_service) : ws_(io_service)
{
response_ << "Hello from obsidian-server!";
}
void handle_accept() {
ws_.async_write(response_.data(), boost::bind(&ws_connection::handle_write, shared_from_this()));
}
void handle_write() {
std::cout << "handle_write" << std::endl;
}
beast::websocket::stream<boost::asio::ip::tcp::socket> ws_;
beast::streambuf response_;
};
class rubymud_server {
public:
using error_code = boost::system::error_code;
rubymud_server(boost::asio::io_service& io_service) : acceptor_(io_service, tcp::endpoint(tcp::v4(), 33435))
{
start_accept();
}
private:
void start_accept()
{
ws_connection::pointer new_connection = ws_connection::create(acceptor_.get_io_service());
acceptor_.async_accept(new_connection->socket(),
boost::bind(
&rubymud_server::handle_accept,
this,
new_connection,
boost::asio::placeholders::error
)
);
}
void handle_accept(ws_connection::pointer new_connection, const error_code& error) {
new_connection->handshake();
start_accept();
}
tcp::acceptor acceptor_;
};
int main(int argc, char* argv[]) {
boost::asio::io_service io_service;
rubymud_server server(io_service);
io_service.run();
}
我不确定我是否理解这个问题,但我会看看我能做些什么。我感觉你不明白io_service
是什么,所以我要说的是:io_service
是一个异步函数的队列。每个异步调用都在 io_service
的队列中。
当您构建 class 时,io_service
会传递给它。 假设 io_service
不会在 class 之前被销毁(这很重要),您的下一个要求是 class 的对象一直存活到 io_service
队列为空。为确保这一点,您 post 函数指向 io_service
,指针为 shared_from_this()
。意思是,只要 io_service
中还有一个 shared_ptr
的实例存在,你的 class 就永远不会被销毁,因为 shared_ptr
计数器永远不会为零。
再说一次:所有这些都假定 io_service
将一直存在,直到 class 的对象被销毁。一旦队列为空,this
的共享指针将自动消失,您的 shared_ptr
可以安全销毁。
这是否回答了您的问题?