Referring to HTTP Server- Single threaded Implementation I am trying to Explicitly control Lifetime of server instance
My Requirements are:
1) I should be able to explicitly destroy the server
2) I need to keep multiple Server Instances alive which should listen to different ports
3) Manager Class maintains list of all active server instances; should be able to create and destroy the server instances by create and drop methods
I am trying to implement Requirement 1 and I have come up with code:
void server::stop()
{
DEBUG_MSG("Stopped");
io_service_.post(boost::bind(&server::handle_stop, this));
}
where handle_stop()
is
void server::handle_stop()
{
// The server is stopped by cancelling all outstanding asynchronous
// operations. Once all operations have finished the io_service::run() call
// will exit.
acceptor_.close();
connection_manager_.stop_all();
}
I try to call it from main()
as:
try
{
http::server::server s("127.0.0.1","8973");
// Run the server until stopped.
s.run();
boost::this_thread::sleep_for(boost::chrono::seconds(3));
s.stop();
}
catch (std::exception& e)
{
std::cerr << "exception: " << e.what() << "\n";
}
Question 1)
I am not able to call server::handle_stop()
.
I suppose io_service_.run()
is blocking my s.stop()
call.
void server::run()
{
// The io_service::run() call will block until all asynchronous operations
// have finished. While the server is running, there is always at least one
// asynchronous operation outstanding: the asynchronous accept call waiting
// for new incoming connections.
io_service_.run();
}
How do I proceed?
Question 2:
For requirement 2) where I need to have multiple server instances
, i think I will need to create an io_service instance
in main and must pass the same instance to all server instances
. Am I right?
Is it mandatory to have only one io_service instance
per process or can I have more than one ?
EDIT
My aim is to implement a class which can control multi server instances:
Something of below sort (Incorrect code // Just giving view, what I try to implement ) I want to achieve- How do i design?
I have confusion regarding io_Service
and how do I cleanly call mng.create()
, mng.drop()
Class Manager{
public:
void createServer(ServerPtr)
{
list_.insert(make_shared<Server> (ip, port));
}
void drop()
{
list_.drop((ServerPtr));
}
private:
io_service iO_;
set<server> list_;
};
main()
{
io_service io;
Manager mng(io);
mng.createServer(ip1,port1);
mng.createServer(ip2,port2);
io.run();
mng.drop(ip1,port1);
}
stop
after blockingrun
, andrun
blocks until there are some unhandled callbacks. There are multiple ways to solve this and it depands from what part of programstop
will be called:server
after some IO operation for example you can simply do as you have triedio_service_.post(boost::bind(&server::handle_stop, this));
, but it should be registered from another thread or from another callback in current thread.io_service::poll()
. It is non-blocking version ofrun
, so you create a loop where you callpoll
until you need to stop server.An HTTP server using a single io_service and a thread pool
An HTTP server using an io_service-per-CPU design
As you say,
run()
won't return until the service is stopped or runs out of work. There's no point callingstop()
after that.In a single-threaded program, you can call
stop()
from an I/O handler - for your example, you could use adeadline_timer
to call it after three seconds. Or you could do something complicated withpoll()
rather thanrun()
, but I wouldn't recommend that.In a multi-threaded program, you could call it from another thread than the one calling
run()
, as long as you make sure it's thread-safe.Yes, that's probably the best thing to do.
You can have as many as you like. But I think you can only run one at a time on a single thread, so it would be tricky to have more than one in a single-threaded program. I'd have a single instance that all the servers can use.