Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Finally I've ended up with some easy-to-use version of server:</p> <p>Usage:</p> <pre><code>boost::shared_ptr&lt;CTCPServer&gt; _serverPtr; void CMyServer::Start() { //First we must create a few threads thread* t = 0; for (int i = 0; i &lt; COHConfig::_iThreads; ++i) { t =_threads.create_thread(bind(&amp;io_service::run, &amp;_io_service)); } //Then we create a server object _serverPtr.reset( new CTCPServer(&amp;_io_service, PORT_NUMBER) ); //And finally run the server through io_service _io_service.post(boost::bind(&amp;CMyServer::RunServer, _serverPtr, &amp;CMyServer::HandleMessage)); } //This is the function which is called by io_service to start our server void CMyServer::RunServer(CTCPServer* s, void (*HandleFunction)(shared_ptr&lt;ip::tcp::socket&gt;, deadline_timer*)) { s-&gt;Run(HandleFunction); } //And this is our connection handler void CMyServer::HandleMessage(shared_ptr&lt; ip::tcp::socket &gt; sockClient, deadline_timer* timer) { cout &lt;&lt; "Handling connection from: " &lt;&lt; sockClient-&gt;remote_endpoint().address().to_string() &lt;&lt; ":" &lt;&lt; sockClient-&gt;remote_endpoint().port() &lt;&lt; endl; //This is some class which gets socket in its constructor and handles the connection scoped_ptr&lt;CMyWorker&gt; myWorker( new CMyWorker(sockClient) ); msgWorker-&gt;Start(); } //Thanks to this function we can stop our server void CMyServer::Stop() { _serverPtr-&gt;Stop(); } </code></pre> <p>The TCPServer.hpp file:</p> <pre><code>#ifndef TCPSERVER_HPP #define TCPSERVER_HPP #if defined(_WIN32) #define BOOST_THREAD_USE_LIB #endif #include &lt;boost/asio.hpp&gt; #include &lt;boost/noncopyable.hpp&gt; #include &lt;boost/shared_ptr.hpp&gt; #include &lt;string&gt; #include &lt;vector&gt; class CTCPServer: private boost::noncopyable { private: bool bKeepRunning; boost::asio::io_service* _io_service; std::string _sPort; boost::asio::ip::tcp::acceptor _acceptor; boost::shared_ptr&lt; boost::asio::ip::tcp::socket &gt; _sockClient; boost::asio::deadline_timer _timer; bool _bIPv6; std::string SessionID(); public: CTCPServer(boost::asio::io_service* ios, const std::string&amp; sPort, bool bIPv6=false): _sPort(sPort), _acceptor(*ios), _timer(*ios), _bIPv6(bIPv6) { _io_service = ios; bKeepRunning = false; }; void Run(void (*HandleFunction)(boost::shared_ptr&lt; boost::asio::ip::tcp::socket &gt; sock, boost::asio::deadline_timer* timer)); void AsyncAccept(void (*HandleFunction)(boost::shared_ptr&lt; boost::asio::ip::tcp::socket &gt; , boost::asio::deadline_timer* )); void AcceptHandler(const boost::system::error_code&amp; e, void (*HandleFunction)(boost::shared_ptr&lt; boost::asio::ip::tcp::socket &gt;, boost::asio::deadline_timer* )); void Stop(); void Stop(void (*StopFunction)()); }; #endif </code></pre> <p>The TCPServer.cpp file:</p> <pre><code>#include "TCPServer.hpp" #include &lt;boost/thread.hpp&gt; #include &lt;boost/bind.hpp&gt; #include &lt;boost/shared_ptr.hpp&gt; #include &lt;boost/thread/mutex.hpp&gt; #include &lt;iostream&gt; using namespace std; string CTCPServer::SessionID() { ostringstream outs; outs &lt;&lt; "[" &lt;&lt; boost::this_thread::get_id() &lt;&lt; "] "; return outs.str(); } void CTCPServer::Run(void (*HandleFunction)(boost::shared_ptr&lt; boost::asio::ip::tcp::socket &gt; , boost::asio::deadline_timer* )) { try { boost::asio::ip::tcp::resolver resolver(*_io_service); boost::asio::ip::tcp::endpoint endpoint; if(_bIPv6) { boost::asio::ip::tcp::resolver::query queryv6(boost::asio::ip::tcp::v6(), _sPort); endpoint = *resolver.resolve(queryv6); } else { boost::asio::ip::tcp::resolver::query queryv4(boost::asio::ip::tcp::v4(), _sPort); endpoint = *resolver.resolve(queryv4); } _acceptor.open(endpoint.protocol()); _acceptor.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); _acceptor.set_option(boost::asio::socket_base::enable_connection_aborted(true)); _acceptor.bind(endpoint); _acceptor.listen(); boost::system::error_code ec; bKeepRunning = true; AsyncAccept(HandleFunction); } catch(std::exception&amp; e) { if(!_bIPv6) std::cerr &lt;&lt; "Exception wile creating IPv4 TCP socket on port "&lt;&lt; _sPort&lt;&lt; ": " &lt;&lt; e.what() &lt;&lt; std::endl; else std::cerr &lt;&lt; "Exception wile creating IPv6 TCP socket on port "&lt;&lt; _sPort&lt;&lt; ": " &lt;&lt; e.what() &lt;&lt; std::endl; } } void CTCPServer::AsyncAccept(void (*HandleFunction)(boost::shared_ptr&lt; boost::asio::ip::tcp::socket &gt; , boost::asio::deadline_timer* )) { if(bKeepRunning) { try { _sockClient.reset(new boost::asio::ip::tcp::socket(*_io_service)); cout &lt;&lt; SessionID() &lt;&lt; "Waiting for connection on port: " &lt;&lt; _sPort &lt;&lt; endl; _acceptor.async_accept(*_sockClient, boost::bind(&amp;CTCPServer::AcceptHandler, this, boost::asio::placeholders::error, HandleFunction)); } catch(exception&amp; e) { string sWhat = e.what(); cout &lt;&lt; SessionID() &lt;&lt; "Error while accepting connection: " &lt;&lt; e.what() &lt;&lt; endl; } } } void CTCPServer::AcceptHandler(const boost::system::error_code&amp; e, void (*HandleFunction)(boost::shared_ptr&lt; boost::asio::ip::tcp::socket &gt;, boost::asio::deadline_timer* )) { if(!e) { try { (*_io_service).post(boost::bind(HandleFunction, _sockClient, &amp;_timer)); AsyncAccept(HandleFunction); } catch(exception&amp; e) { cout &lt;&lt; SessionID() &lt;&lt; "Exception: " &lt;&lt; e.what() &lt;&lt; endl; } } } void CTCPServer::Stop() { cout &lt;&lt; SessionID() &lt;&lt; "STOP port " &lt;&lt; _sPort &lt;&lt; endl; if(!bKeepRunning) return; bKeepRunning = false; try { _sockClient-&gt;close(); } catch(exception&amp; e) { cout &lt;&lt; SessionID() &lt;&lt; "Exception: " &lt;&lt; e.what() &lt;&lt; endl; } try { _acceptor.cancel(); } catch(exception&amp; e) { cout &lt;&lt; SessionID() &lt;&lt; "Exception: " &lt;&lt; e.what() &lt;&lt; endl; } try { _acceptor.close(); } catch(exception&amp; e) { cout &lt;&lt; SessionID() &lt;&lt; "Exception: " &lt;&lt; e.what() &lt;&lt; endl; } } void CTCPServer::Stop(void (*StopFunction)()) { Stop(); StopFunction(); } </code></pre> <p>It's also very easy to modify to be IPv6 compatible. It's already tested and working very well. Just copy it and use!</p>
 

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