c++ - 在循环中 boost asio 问题

标签 c++ boost boost-asio

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

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

  2. 如果我们在服务器对先前消息的回答之前发送一些消息,我的代码是否可以正常工作?

这是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();

}

最佳答案

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

此外,您多次调用async_send,而没有等待上一个async_send的完成处理程序,这也是不正确的。

请参阅 asio 文档以找出正确的使用模式。

关于c++ - 在循环中 boost asio 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13080476/

相关文章:

c++ - 为什么 scanf 似乎跳过了输入?

c++ - 使用 int 和 string boost::interprocess 映射

c++ - boost asio async_read_some 超时

C++ 外观避免复制

c++ - QSet:qHash 和自定义类错误

C++ : create custom function dispatcher from variadic template

c++ - 无法包含来自 boost 库的 header

c++ - 如何使用boost::beast连续流式传输文件

c++ - 带 bo​​ost asio 的多线程服务器

c++ - boost asio SSL 服务器错误 : called a function you should not call