Destroying server instance : ASIO C++

2019-08-31 06:00发布

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);
    }

2条回答
2楼-- · 2019-08-31 06:23
  1. You are right, it's not working because you call stop after blocking run, and run blocks until there are some unhandled callbacks. There are multiple ways to solve this and it depands from what part of program stop will be called:
    • If you can call it from another thread, then run each instance of server in separate thread.
    • If you need to stop server after some IO operation for example you can simply do as you have tried io_service_.post(boost::bind(&server::handle_stop, this));, but it should be registered from another thread or from another callback in current thread.
    • You can use io_service::poll(). It is non-blocking version of run, so you create a loop where you call poll until you need to stop server.
  2. You can do it both ways. Even with the link you provided you can take a look at:
    • HTTP Server 3 - An HTTP server using a single io_service and a thread pool
    • and HTTP Server 2 - An HTTP server using an io_service-per-CPU design
查看更多
闹够了就滚
3楼-- · 2019-08-31 06:31

I am not able to call server::handle_stop().

As you say, run() won't return until the service is stopped or runs out of work. There's no point calling stop() after that.

In a single-threaded program, you can call stop() from an I/O handler - for your example, you could use a deadline_timer to call it after three seconds. Or you could do something complicated with poll() rather than run(), 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.

For [multiple servers] I think I will need to create an io_service instance in main

Yes, that's probably the best thing to do.

Is it mandatory to have only one io_service instance per process or can I have more than one?

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.

查看更多
登录 后发表回答