简体   繁体   中英

Boost Asio, Multiple threads and multiple io_service

I want to develop a server use multiple threads and multiple io_service instance(each thread use an io_service instance) to listen at a port. For each io_service instance I create a corresponding boost::asio::ip::tcp::acceptor object. I try this code:

 using namespace boost::asio;
    ...
    io_service io_service_;
    io_service io_service_1;

    ip::tcp::acceptor* acceptor_;
    acceptor_ = new ip::tcp::acceptor(io_service_);
    ip::tcp::endpoint ep( ip::tcp::v4(), LISTEN_PORT);
    acceptor_->open(ep.protocol());
    acceptor_->bind(ep);
    acceptor_->listen();

    ip::tcp::acceptor* acceptor_1;
    acceptor_1 = new ip::tcp::acceptor(io_service_1);
    acceptor_1->open(ep.protocol());
    acceptor_1->bind(ep);
    acceptor_1->listen();
    ...

    boost::thread th( boost::bind(&io_service::run, &io_service_));
    boost::thread th( boost::bind(&io_service::run, &io_service_1));
    ...

when running will display error dialog:

boost::exception_detail::clone_impl< boost::exception_detail::error_info_injector > at memory location 0x001FF704.

can you help me how to make a server with Multiple threads, each thread use an io_service instance?

Update: as I read in Boost.Asio C++ Network Programming, have 3 way to use io_service with thread:

  1. Single-thread with one io_service and one handler thread(thread running io_service::run())
  2. Multi-threaded with a single io_service instance and several handler threads
  3. Multi-threaded with several io_service instances and several threads

I can implement case 1 and 2. But with case 3, I don't know how to implement it to handle many concurrent connections, should I use 1 thread to handle 1 io_service(as above)? Is case 3 has better performance(can handle more concurrent connections) than case 2?

You can use multiple threads, but you need to use 1 acceptor for a port.

IO services are thread-safe, so you can use one service on many threads.

You can even have multiple io services, no problem. You can't bind multiple acceptors to the same port though (unless you bind to different logical network interfaces, perhaps, but that's not really "the same port" then).

#include <boost/asio.hpp>
#include <boost/thread.hpp>

using namespace boost::asio;
using namespace boost;

int main() {
    io_service io_service_;

    ip::tcp::acceptor acceptor_(io_service_, { {}, 6767 });
    acceptor_.bind({ ip::tcp::v4(), 6767 });

    boost::thread_group tg;
    for (unsigned i = 0; i < thread::hardware_concurrency(); ++i)
        tg.create_thread(boost::bind(&io_service::run, &io_service_));

    // ...
    //
    tg.join_all();
}

You can only have one acceptor listening on a given port. If you want to handle multiple clients with one port, you'll need to set the option reuse_address on your acceptor . That way the socket you pass to async_accept() will use a different port, leaving your listen port free to accept a connection from another client.

boost::asio::io_service ios_;
boost::asio::ip::tcp::acceptor acceptor_(ios_);

void handle_client(boost::shared_pointer<boost::asio::ip::tcp::socket> sock);
void start_accept();

int main() {
    boost::asio::ip::tcp::endpoint ep(ip::tcp::v4(), LISTEN_PORT);
    acceptor_.open(ep.protocol());
    acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    acceptor_.bind(ep);
    acceptor_.listen();
    boost::thread_group threads;
    for (int i = 0; i < NUM_WORKER_THREADS; ++i) {
        threads.create_thread(boost::bind(&io_service::run, &ios_));
    }
    start_accept();
    threads.join_all();
}

void start_accept() {
    boost::shared_pointer<boost::asio::ip::tcp::socket> sock(ios_);
    acceptor_.async_accept(*sock, boost::bind(handle_client, sock));
}

void handle_client(boost::shared_pointer<boost::asio::ip::tcp::socket> sock) {
    start_accept();
    // talk to the client
}

See Boost's HTTP server example for a more complete example.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM