Note that there are some explanatory texts on larger screens.

plurals
  1. POboost::asio multithreaded asynchronous accept with blocking read/write server
    primarykey
    data
    text
    <p>My idea was to create X threads, run it using KeepRunning method which has endless loop calling _io_service.run() and send tasks to _io_service when received a new connection using _io_service.poll() in async_accept handler. </p> <p>I run the server with a code like this:</p> <pre><code> oh::msg::OHServer s("0.0.0.0", "9999", 200); ConsoleStopServer = boost::bind(&amp;oh::msg::OHServer::Stop, &amp;s); SetConsoleCtrlHandler(bConsoleHandler, TRUE); s.Run(); </code></pre> <p>but when I receive one connection, then serve it in Post() method using blocking read/writes in MsgWorker class, then all the threads are being closed. </p> <p>I have code like below (it's some mix from http server3 asio example and mine):</p> <pre><code>OHServer::OHServer(const std::string&amp; sAddress, const std::string&amp; sPort, std::size_t tps) : _nThreadPoolSize(tps), _acceptor(_io_service), _sockClient(new boost::asio::ip::tcp::socket(_io_service)) { // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR). boost::asio::ip::tcp::resolver resolver(_io_service); boost::asio::ip::tcp::resolver::query query(sAddress, sPort); boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query); _acceptor.open(endpoint.protocol()); _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); _acceptor.bind(endpoint); _acceptor.listen(); _acceptor.async_accept( *_sockClient, boost::bind( &amp;OHServer::AcceptConnection, this, boost::asio::placeholders::error ) ); } void OHServer::KeepRunning() { global_stream_lock.lock(); std::cout &lt;&lt; "[" &lt;&lt; boost::this_thread::get_id() &lt;&lt; "] Thread Start" &lt;&lt; std::endl; global_stream_lock.unlock(); while( true ) { try { boost::system::error_code ec; _io_service.run( ec ); if( ec ) { global_stream_lock.lock(); std::cout &lt;&lt; "[" &lt;&lt; boost::this_thread::get_id() &lt;&lt; "] Error: " &lt;&lt; ec &lt;&lt; std::endl; global_stream_lock.unlock(); } break; } catch( std::exception &amp; ex ) { global_stream_lock.lock(); std::cout &lt;&lt; "[" &lt;&lt; boost::this_thread::get_id() &lt;&lt; "] Exception: " &lt;&lt; ex.what() &lt;&lt; std::endl; global_stream_lock.unlock(); } } global_stream_lock.lock(); std::cout &lt;&lt; "[" &lt;&lt; boost::this_thread::get_id() &lt;&lt; "] Thread Finish" &lt;&lt; std::endl; global_stream_lock.unlock(); } void OHServer::Run() { // Create a pool of threads to run all of the io_services. for (std::size_t i = 0; i &lt; _nThreadPoolSize; ++i) { boost::shared_ptr&lt;boost::thread&gt; thread(new boost::thread( boost::bind(&amp;OHServer::KeepRunning, this))); threads.push_back(thread); } cout &lt;&lt; "Hit enter to close server" &lt;&lt; endl; cin.get(); } void OHServer::Stop() { boost::system::error_code ec; _acceptor.close(ec); _sockClient-&gt;shutdown( boost::asio::ip::tcp::socket::shutdown_both, ec ); _sockClient-&gt;close( ec ); _io_service.stop(); // Wait for all threads in the pool to exit. for (std::size_t i = 0; i &lt; threads.size(); ++i) { threads[i]-&gt;join(); cout &lt;&lt; "threads[ "&lt;&lt; i &lt;&lt; "]-&gt;join();" &lt;&lt; endl; } } void OHServer::Post() { std::cout &lt;&lt; "Accepted new connection." &lt;&lt; std::endl; CMsgWorker *msgWorker = new CMsgWorker(_sockClient); msgWorker-&gt;Start(); delete msgWorker; } void OHServer::AcceptConnection(const boost::system::error_code&amp; e) { if (!e) { _io_service.post(boost::bind(&amp;OHServer::Post, this)); _acceptor.async_accept( *_sockClient, boost::bind( &amp;OHServer::AcceptConnection, this, boost::asio::placeholders::error ) ); } } </code></pre> <p>What should I do for the threads to be still waiting for some work to do from _io_service?</p> <p>Thanks for any help!</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload