Boost logo

Boost Users :

Subject: Re: [Boost-users] Asio question
From: asio_user (asonawane_at_[hidden])
Date: 2008-10-06 10:31:40


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_at_[hidden]
> 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.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net