Hi,
I am using Asio in Boost version 1.36.0 and I have a question regarding
recursive call to a completion handler. I have implemented a class
similar to the one from the examples of asio acceptor.
I would like to know if there is a way to recursively call handle_accept
() within handle_accept() and break on condition when the socket is
closed. (Please see my comment in the code ). Does Asio allow such
implementation or is there another way to handle this condition.
#include "server.hpp"
#include
I would like to know if there is a way to recursively call handle_accept () within handle_accept() and break on condition when the socket is closed. (Please see my comment in the code ).
I don't see any recurtion in your code, you just perform a new async_accept after the previous one ends - this is legitimate and shouldn't cause any problem.
Igor R wrote:
I would like to know if there is a way to recursively call handle_accept () within handle_accept() and break on condition when the socket is closed. (Please see my comment in the code ).
I don't see any recurtion in your code, you just perform a new async_accept after the previous one ends - this is legitimate and shouldn't cause any problem. _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Thanks Igor. Let me explain in detail. What I intend to do is the following: 1. Server app accepts connections from various clients does some data processing and returns the result back to the client on the same established connection. 2. Client app connects to the server sends a login and receives a keep alive. The connection between client and server is maintained as long as either side disconnets or logs out, where the socket on the other end is closed. When the connection is dropped I need to create a new acceptor_connection and keep listening for clients to reconnect. For this senario to work I make a call to async_accept after the previous one ends. I have to do the same at the client end so that both apps use the same socket to read, write and exchange messages. What I would like to know is that is there a better way to handle this situation (i.e. calling an accept on the same socket repeatedly). The asio examples do not show this type of handling. In my tests I see that the server app takes up about 50% of CPU as it tries to make repeated accepts the same happens with client app which makes an async_connect at the established endpoint. Any help is greatly appreciated. I use 3 classes for Acceptor (Server), Initiator(Client) and Connection used by both. Here is the code for each (removed some code): ============================================================================= // 1. Class Connection class AsioConnection { public: AsioConnection(boost::asio::io_service& io_service) : m_Socket(io_service) {} AsioConnection(boost::asio::io_service& io_service, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) : m_Socket(io_service) { m_endpoint = *endpoint_iterator; m_Socket.async_connect(m_endpoint, boost::bind(&AsioConnection::HandleConnect, this, boost::asio::placeholders::error, ++endpoint_iterator)); } ~AsioConnection() {} boost::asio::ip::tcp::socket& GetSocket() { return m_Socket; } bool drop() { return !m_Socket.is_open() ? true : false; } void disconnect() { m_Socket.shutdown( boost::asio::ip::tcp::socket::shutdown_both ); m_Socket.close(); } void Close() { m_Socket.close(); } void Connect() { if(m_Socket.is_open() && m_Socket.available()) { boost::asio::async_read_until(m_Socket, m_InBuf,boost::regex("\00110="), boost::bind(&AsioConnection::HandleRead, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); } } private: boost::asio::ip::tcp::socket m_Socket; boost::asio::ip::tcp::endpoint m_endpoint; void HandleConnect(const boost::system::error_code& error, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) { if ( !error ) { DoSomething(); } else if (endpoint_iterator != boost::asio::ip::tcp::resolver::iterator()) { m_Socket.close(); m_endpoint = *endpoint_iterator; m_Socket.async_connect(m_endpoint, boost::bind(&AsioConnection::HandleConnect, this, boost::asio::placeholders::error, ++endpoint_iterator)); return; } m_Socket.async_connect(m_endpoint, boost::bind(&AsioConnection::HandleConnect, this, boost::asio::placeholders::error, endpoint_iterator)); } void DoSomething() {} bool send( const std::string & sMsg ) { if( m_Socket.is_open() && sMsg.size() ) { boost::asio::async_write(m_Socket,boost::asio::buffer(sMsg.c_str(),sMsg.size()),boost::asio::transfer_all(), boost::bind(&AsioConnection::HandleWrite, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); return true; } else return false; } void HandleWrite(const boost::system::error_code& ec,size_t bytes_transferred) {} void HandleRead( const boost::system::error_code& ec, size_t bytes_transferred ) { //Do futher processing if ( ec == boost::asio::error::connection_aborted || ec == boost::asio::error::connection_reset ) { disconnect(); } } }; typedef boost::shared_ptr<AsioConnection> AsioConnectionPtr; //2 Class Acceptor class TCPAcceptor { public: boost::asio::ip::tcp::acceptor m_acceptor; boost::asio::ip::tcp::endpoint m_endpoint; AsioConnectionPtr acceptor_conn_ptr; void OpenAcceptor() { acceptor_conn_ptr.reset(new AsioConnection(m_acceptor.get_io_service())); m_acceptor.async_accept(acceptor_conn_ptr->GetSocket(), boost::bind(&TCPAcceptor::handle_accept, this, acceptor_conn_ptr, boost::asio::placeholders::error)); } void handle_accept(AsioConnectionPtr acceptor_conn_ptr, const boost::system::error_code& error) { if ( !error || error == boost::asio::error::already_open ) { acceptor_conn_ptr->DoSomething() if(acceptor_conn_ptr->drop()) acceptor_conn_ptr.reset(new AsioConnection(m_acceptor.get_io_service())); m_acceptor.async_accept(acceptor_conn_ptr->GetSocket(), boost::bind(&TCPAcceptor::handle_accept, this, acceptor_conn_ptr, boost::asio::placeholders::error)); } else OpenAcceptor(); } void CloseAcceptor() { m_acceptor.close(); } TCPAcceptor( boost::asio::io_service& iosvr, const std::string host, const unsigned short port, const bool bReuseAddress, const bool bNoDelay ) : m_acceptor(iosvr), m_endpoint(boost::asio::ip::address::from_string(host.c_str()), port) {} }; //3. Class Asio Initiator class TCPInitiator { public: boost::asio::ip::tcp::socket m_InitiatorSocket;//variable to hold io_service object boost::asio::ip::tcp::endpoint m_endpoint; boost::asio::ip::tcp::resolver m_resolver; AsioConnectionPtr initiator_conn_ptr; void OpenInitiator() { m_resolver.async_resolve(m_endpoint, boost::bind(&TCPInitiator::HandleResolve, this, boost::asio::placeholders::error, boost::asio::placeholders::iterator)); } void HandleResolve( const boost::system::error_code& err, boost::asio::ip::tcp::resolver::iterator endpoint_iterator) { if (!err) { initiator_conn_ptr.reset(new AsioConnection(m_InitiatorSocket.get_io_service(),endpoint_iterator, m_SessionID,m_endpoint.address().to_string(),m_endpoint.port())); } else OpenInitiator(); } void CloseInitiator() { m_InitiatorSocket.close(); } TCPInitiator ( boost::asio::io_service& iosvr,const std::string& host, unsigned short port, const long lReconnect, const FIX::SessionID& sessID ): m_lReconnectInterval(lReconnect), m_SessionID(sessID), m_endpoint(boost::asio::ip::address::from_string(host.c_str()), port), m_InitiatorSocket(iosvr), m_resolver(iosvr) {} }; ===================================================================== Thanks -- View this message in context: http://www.nabble.com/Asio-question-tp19788349p19839118.html Sent from the Boost - Users mailing list archive at Nabble.com.
participants (3)
-
Amit Sonawane
-
asio_user
-
Igor R