boost async_read_until将match_condition和限制大小结合起来进行读取

时间:2015-08-28 14:53:47

标签: c++ boost boost-asio

有没有办法在找到匹配的字符或收到128个字节之前将两个条件组合起来?

可以限制streambuf尺寸:

@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *labelHeight;


- (void) viewDidLoad{
   [self.label sizeToFit];
   labelHeight.constant = self.label.frame.size.height;
}

但是当处理程序有原因"元素未找到"流中没有可用数据,传输的字节也是0。

想法是阅读直到''或接收128字节

我的代码如下:

inBuf = std::make_shared< boost::asio::streambuf>(limit_size);

1 个答案:

答案 0 :(得分:2)

自定义MatchCondition条件不允许限制从流中读取的字节数不超过n个字节数。 read_until()函数族都允许从Streamstreambuf读取分隔符以外的数据。本质上,read_until()将从streambuf准备缓冲区,从Stream读取一大块数据到准备好的缓冲区中,然后使用MatchCondition检查完成条件是否完成已经满足了。

如果找到所需的分隔符,为了读取不超过n字节并提前完成,请考虑构建具有最大大小的boost::asio::streambuf,然后使用read_until()操作。例如,如果找到“128”分隔符,则以下内容将从流中读取不超过;个字节并提前完成:

boost::asio::streambuf buffer(128);
boost::system::error_code error;
std::size_t bytes_transferred = boost::asio::read_until(
    stream, buffer, ';', error);

在上面的例子中

  • 如果读取128字节并且未找到分隔符,则error将为boost::asio::error::not_foundbuffer.size()将为128
  • 如果找到了分隔符,则error将成功,bytes_transferred将是最多包含buffer输入序列中的分隔符的字节数。请注意,buffer.size()可能会大于bytes_transferred,但不会超过128
  • 如果未读取128字节且未找到分隔符,则error将包含有关读取操作失败原因的相应错误条件,例如boost::asio::error::eof如果远程同行关闭了连接。

以下是streambuf的行为的完整示例demonstrating

#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/bind.hpp>

// This example is not interested in the handlers, so provide a noop function
// that will be passed to bind to meet the handler concept requirements.
void noop() {}

std::string make_string(boost::asio::streambuf& streambuf, std::size_t n)
{
 return {buffers_begin(streambuf.data()),
         buffers_begin(streambuf.data()) + n};
}

int main()
{
  using boost::asio::ip::tcp;
  boost::asio::io_service io_service;

  // Create all I/O objects.
  tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0));
  tcp::socket server_socket(io_service);
  tcp::socket client_socket(io_service);

  // Connect client and server sockets.
  acceptor.async_accept(server_socket, boost::bind(&noop));
  client_socket.async_connect(acceptor.local_endpoint(), boost::bind(&noop));
  io_service.run();

  // Write data to server that contains a delimiter.
  auto bytes_written = boost::asio::write(server_socket,
      boost::asio::buffer(std::string("12345;67890")));

  // Wait for all data to be received.
  while (bytes_written != client_socket.available())
  {
    std::this_thread::sleep_for(std::chrono::seconds(1));
  }

  // Create a streambuf too small to read up to the delimter.
  {
    const std::size_t MAX_SIZE = 2;
    boost::asio::streambuf read_buffer(MAX_SIZE);

    boost::system::error_code error;
    auto bytes_read = boost::asio::read_until(
        client_socket, read_buffer, ';', error);

    // Expect an error as the delim was not found, so the read_until
    // return value is 0.  However, data was read into the buffer.
    assert(boost::asio::error::not_found == error);
    assert(bytes_read == 0);
    assert(read_buffer.size() == 2); // "12" out of "12345;67890";

    // Verify additional data was not read from the stream.
    assert((bytes_written - MAX_SIZE) == client_socket.available());
  }

  // Default construct a streambuf, which has a large max.
  {
    boost::asio::streambuf read_buffer;

    // Read from the socket.
    boost::system::error_code error;
    auto bytes_read = boost::asio::read_until(
        client_socket, read_buffer, ';', error);

    // Verify that at least "345;" was read.
    assert(!error);
    assert(bytes_read != 0);
    assert(make_string(read_buffer, bytes_read) == "345;");

    // Not a guarantee, but the implementation may (and likely will)
    // read beyond the delimiter.  If so, the streambuf's size will
    // be larger than return value from read_until, as it returns the
    // number of bytes up to and including the delimiter.
    if (bytes_read < read_buffer.size())
    {
      std::cout << "Read beyond delimiter" << std::endl;
    }
  }

  std::cout << "bytes remaining: " << client_socket.available() <<
               std::endl;
}

输出:

Read beyond delimiter
bytes remaining: 0
相关问题