代码之家  ›  专栏  ›  技术社区  ›  ruipacheco

长度未知时如何读取数据?

  •  3
  • ruipacheco  · 技术社区  · 6 年前

    auto listener::read(std::function<void(std::error_code ec, packet packet)> callback) noexcept -> void {
      m_buffer.resize(1);
      m_buffer.shrink_to_fit();
    
      asio::async_read(*m_socket, asio::buffer(m_buffer), asio::transfer_exactly(1),
                       [&, callback](std::error_code ec, std::size_t length) {
                         const auto available = m_socket->available();
                         packet tmp;
                         tmp.resize(available);
                         asio::async_read(*m_socket, asio::buffer(tmp), asio::transfer_exactly(available));
                         tmp.insert(tmp.begin(), std::make_move_iterator(m_buffer.begin()),
                                    std::make_move_iterator(m_buffer.end()));
                         callback(ec, std::move(tmp));
                       });
    }
    

    ( packet std::vector<unsigned char>

    我不知道如何在没有临时文件的情况下创建这个。我无法调整大小 m_buffer 一开始,因为我不知道会有多少数据。我试着用 仅在lambda内调整大小以匹配 available +1但我最终丢失了存储在中的第一个字节 m_缓冲区 .

    当需要未知长度的数据包时,有没有更有效的方法来实现这一点?

    1 回复  |  直到 6 年前
        1
  •  1
  •   rafix07    6 年前

    首先,你不能这样做:

     asio::async_read(*m_socket, asio::buffer(tmp), asio::transfer_exactly(available)); //[1]
     tmp.insert(tmp.begin(), std::make_move_iterator(m_buffer.begin()),
                                std::make_move_iterator(m_buffer.end())); // [2]
    

    在[1]中,异步操作开始。 async_read tmp ,第二个(异步操作)填充 tmp 根据一些数据。 您可以使用同步操作: asio::read 而不是 asio::async_read insert 仅在读取数据时执行。


    boost::asio::动态\u缓冲区 :

    struct listener {
     vector<char> m_buffer;
     // others members
    };
    
    void listener::read(std::function<void(std::error_code ec, packet p)> callback) 
    {
      boost::asio::async_read(m_socket, boost::asio::dynamic_buffer(m_buffer), boost::asio::transfer_exactly(1),
                                                     ^^^^^^^^^^^^^
                 [&, callback](std::error_code ec, std::size_t length) 
                 {
                     const auto available = m_socket.available();
                     boost::asio::async_read(m_socket, boost::asio::dynamic_buffer(m_buffer), 
                                                                    ^^^^^^^^^^^^^
                          boost::asio::transfer_exactly(available),
                       [this,callback](const boost::system::error_code& ec, size_t)
                       {
                          callback(ec, std::move(m_buffer));
                       });
                });
    }
    

    m_buffer 异步操作 . 你不需要手动操作。如您所见,我添加了新的处理程序->哪里叫 callback(ec,move(m_buffer)) . 调用此处理程序时,我们知道读取操作结束。