为什么async_read_until()没有wating?

时间:2017-11-11 20:14:24

标签: c++ boost-asio boost-serialization

当我使用带有档案的boost :: async_read_until()时,它不会按照预期等待。由于我的客户端和服务器有点长,我将展示问题所在的方法。请帮我处理它们

//client
void doChat()
    {
        cout << "Enter message: ";
        std::getline(cin, m_info.m_message);
        m_info.m_id = 7;

        {
            std::stringstream ss;
            boost::archive::binary_oarchive out(ss);

            out & m_info;

            m_string_stream = ss.str();
            m_string_stream += '\n';
        }

        m_sock.async_write_some(boost::asio::buffer(m_string_stream), 
            [this](const boost::system::error_code& ec, std::size_t bytes) 
        {
            if (ec == 0){
                doChat();
            } 
        });

因为我不知道如何直接发送存档对象,我使用字符串添加'\ n'假设服务器将读取直到'\ n'

//server
void doChatserver(std::shared_ptr<client> connection)
    {
        boost::asio::async_read_until(connection->m_sock, connection->m_stream_buffer, '\n', 
            [this, connection](const boost::system::error_code& ec, std::size_t bytes)
        {
            if (ec == 0)
            {
                {
                    boost::archive::binary_iarchive in_archive(connection->m_stream_buffer);

                    in_archive & connection->m_info;
                }
                doChatserver(connection); //--> problem when calling secondly
            }
        });
    } 

服务器从客户端读取后,作为回调它再次调用doChatserver(),但这次它不等待客户端的数据来,它只是崩溃! 那么您认为有什么问题?

1 个答案:

答案 0 :(得分:1)

不是一个完整的答案,只是一些指示......

1)您应该反复调用async_write_some,直到缓冲区为空。

请参阅async_write_some文档中的注释:

  

写操作可能不会将所有数据传输到对等方。如果需要确保在异步操作完成之前写入所有数据,请考虑使用async_write函数。

因此,使用async_write更容易,这可以保证缓冲区中的所有数据都被发送。

2)您应该将\n从接收到的数据末尾删除,然后再将其传递给iarchive,因为它不属于您的二进制存档。

3)如果您的二进制流包含字节0A\n)怎么办? read_until会过早停止。考虑将数据的长度发送为整数(例如前4个字节),然后是数据本身。处理二进制数据时,请在\n之前阅读。

发送功能:

  • 计算二进制数据大小N
  • 构造数据大小(4字节)+数据(N字节)的缓冲区
  • 发送整个缓冲区(N + 4个字节)

接收功能:

  • 读取4个字节
  • 读取前4个字节中指定的N个数据字节

    示例:

    boost::asio::read(socket, streambuf, boost::asio::transfer_exactly(n), ec);

4)使用调试器。打破并查看已读入connection->m_info的内容。