在循环中提升asio问题

时间:2012-10-26 03:51:21

标签: c++ boost boost-asio

有人可以帮我解决以下问题吗?

  1. 我正在尝试在while循环中调用async_send。数据被正确发送到服务器,但是根本没有调用onSend处理程序...如果我不使用while循环一切正常(数据被发送和接收,所有处理程序都被调用)

  2. 如果我们在服务器的回答之前发送一些msgs,我的代码是否会正常工作?

  3. 这是TCP客户端代码

    class TCPClient
    {
        public:
            static const size_t maxBufLen = 100;
            static const size_t MAX_INPUT_SIZE = 10;
    
            TCPClient(boost::asio::io_service& IO_Service, tcp::resolver::iterator EndPointIter);
            void close();
    
        private:
            boost::asio::io_service& m_IOService;
            tcp::socket m_Socket;
    
            char recieveBuffer[maxBufLen];
    
            void promptTxMsgLoop();
            void onConnect(const boost::system::error_code& ErrorCode, tcp::resolver::iterator EndPointIter);
            void onReceive(const boost::system::error_code& ErrorCode);
            void onSend(const boost::system::error_code& ErrorCode);
            void doClose();
    };
    
    
    TCPClient::TCPClient(boost::asio::io_service& IO_Service, tcp::resolver::iterator EndPointIter)
    : m_IOService(IO_Service), m_Socket(IO_Service)
    {
        tcp::endpoint EndPoint = *EndPointIter;
        recieveBuffer[0] = '\0';
    
        m_Socket.async_connect(EndPoint,
            boost::bind(&TCPClient::onConnect, this, boost::asio::placeholders::error, ++EndPointIter));
    }
    
    
    void TCPClient::onConnect(const boost::system::error_code& ErrorCode, tcp::resolver::iterator EndPointIter)
    {
        if (ErrorCode == 0)
        {
            this->promptTxMsgLoop();
        }
        else if (EndPointIter != tcp::resolver::iterator())
        {
            cout << "m_Socket.close();!" << endl;
            m_Socket.close();
            tcp::endpoint EndPoint = *EndPointIter;
    
            m_Socket.async_connect(EndPoint, 
                boost::bind(&TCPClient::onConnect, this, boost::asio::placeholders::error, ++EndPointIter));
        }
    }
    
    void TCPClient::promptTxMsgLoop()
    {
        recieveBuffer[0] = '\0';
        while (true)
        {
            cout << "> " ;
            string tmp;
            cin >> tmp;
    
            cout << "Entered: " << tmp << endl;
            tmp += "\0";
    
            if (tmp.length() < MAX_INPUT_SIZE-1)
            {
                try
                {
                    //lock untill buffer is emty
                    while (strlen(recieveBuffer) > 1)
                    {
    
                    }
                    //onSend handler is never is called inside while loop 
                    m_Socket.async_send(boost::asio::buffer(tmp.c_str(),tmp.length()+1),
                        boost::bind(&TCPClient::onSend, this, boost::asio::placeholders::error));
                }
                catch(exception &e)
                {
                    cerr << "Cannot add msg to send queue... " << e.what() << endl;
                }
            }
            else
                cout << "Error: input string is too long. Max length is " << MAX_INPUT_SIZE-1 << endl;
        }
    }
    
    void TCPClient::onSend(const boost::system::error_code& ErrorCode)
    {
        cout << "Msg has been sent..." << endl;
    
        if (strlen(recieveBuffer) > 1)
            cout << "ERROR: recieveBuffer in not epmty. Data is overritten!" << endl;
    
        if (!ErrorCode)
        {
            m_Socket.async_receive(boost::asio::buffer(recieveBuffer, TCPClient::maxBufLen),
                boost::bind(&TCPClient::onReceive, this, boost::asio::placeholders::error));
        }
        else
        {
            cout << "onSend closing" << endl;
            cout << "ERROR! onSend..." << ErrorCode << endl;
            doClose();
        }
    }
    
    void TCPClient::onReceive(const boost::system::error_code& ErrorCode)
    {
        cout << "Msg has been received..." << endl;
    
        if (ErrorCode == 0)
        {
            cout << recieveBuffer << endl;
            cout << "msg length: " << strlen(recieveBuffer) << endl;
    
            //unlock buffer
            recieveBuffer[0] = '\0';
        } 
        else 
        {
            cout << "ERROR! onReceive..." << ErrorCode << endl;
            doClose();
        }
    }
    
    void TCPClient::doClose()
    {
        m_Socket.close();
    }
    
    int main()
    {
        try 
        {
            boost::asio::io_service IO_Service;
            tcp::resolver Resolver(IO_Service);
            tcp::resolver::query Query("127.0.0.1", "1");
            tcp::resolver::iterator EndPointIterator = Resolver.resolve(Query);
            TCPClient Client(IO_Service, EndPointIterator);
            boost::thread ClientThread(boost::bind(&boost::asio::io_service::run, &IO_Service));
            ClientThread.join();
            Client.close();
        } 
        catch (exception& e)
        {
            cerr << e.what() << endl;
        }
    
        cout << "\nClosing";
        getch();
    
    }
    

1 个答案:

答案 0 :(得分:2)

在“onConnect”完成处理程序中,您调用执行无限promptTxMsgLoop循环的while,因此您实际上永远不会让io_service继续其工作 - 因此不会有完成处理程序再次被调用。

此外,你多次调用async_send,而不等待前一个async_send的comletion处理程序,这也是不正确的。

请参阅asio文档以了解正确的使用模式。