我一直在使用boost中针对单线程服务器的以下示例:https://www.boost.org/doc/libs/1_81_0/doc/html/boost_asio/example/cpp03/http/server/
我修改了服务器类,以便可以启动、结束和重新启动服务器。
server_impl::server_impl(
const std::string& address,
const std::string& port,
const std::shared_ptr<boost::asio::io_context>& io_context,
const std::shared_ptr<connection_manager>& connection_manager,
const std::shared_ptr<request_handler>& request_handler) :
io_context_(io_context),
acceptor_(*io_context_),
connection_manager_(connection_manager),
new_connection_(),
request_handler_(request_handler),
address_(address),
port_(port)
{
}
void server_impl::start_server()
{
// Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
boost::asio::ip::tcp::resolver resolver(*io_context_);
boost::asio::ip::tcp::endpoint endpoint =
*resolver.resolve(address_, port_).begin();
acceptor_.open(endpoint.protocol());
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
acceptor_.bind(endpoint);
acceptor_.listen();
start_accept();
}
void server_impl::end_server()
{
/* The server is stopped by cancelling all outstanding asynchronous
operations */
acceptor_.close();
connection_manager_->stop_all();
}
void server_impl::start_accept()
{
new_connection_.reset(new connection_impl(
io_context_,
connection_manager_,
request_handler_));
acceptor_.async_accept(
new_connection_->socket(),
boost::bind(
&server_impl::handle_accept,
this,
boost::asio::placeholders::error));
}
void server_impl::handle_accept(const boost::system::error_code& e)
{
/* Check whether the server was stopped before this completion handler had a
chance to run. */
if (!acceptor_.is_open())
{
return;
}
if (!e)
{
connection_manager_->start(new_connection_);
}
start_accept();
}
void server_impl::serve_static(const std::string& path)
{
request_handler_->serve_from_directory(path);
}
你可以看到我把解析和监听从构造函数移到了start_server
函数,然后把handle_stop
的内容移到了end_server
。
如果我只是启动服务器并像这样结束它一次(使用一个线程在30秒后结束,只是为了测试):
int main()
{
server->serve_static("/path/to/html");
server->start_server();
std::thread t([&server](){sleep(30); server->end_server();});
io_context->run();
t.join();
}
但是如果我尝试在服务器停止后重新启动它,io_context->run();
会立即返回,我认为它应该阻塞,因为async_accept
在接受器上再次被调用:
int main()
{
server->serve_static("/path/to/html");
server->start_server();
std::thread t([&server](){sleep(30); server->end_server();});
io_context->run();
t.join();
server->start_server();
io_context->run();
}
服务器在前30秒工作,然后像预期的那样停止,但是当再次启动时,run
立即返回,并且不会再次启动。
1条答案
按热度按时间bfrts1fy1#
根据升压文档:
对
run()
、run_one()
、poll()
或poll_one()
的后续调用将立即返回,除非之前调用了restart()
。