gpt4 book ai didi

c++ - boost async_read_until 将 match_condition 与限制大小结合起来读取

转载 作者:行者123 更新时间:2023-11-30 03:49:43 25 4
gpt4 key购买 nike

有没有办法结合两个条件读取,直到找到匹配字符或收到 128 个字节?

可以限制 streambuf 的大小:

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

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

这个想法是读到';'或接收到 128 个字节

我的代码如下:

class match_char
{
public:
explicit match_char(char c, int len) : c_(c), len_(len) {}

template <typename Iterator>
std::pair<Iterator, bool> operator()(
Iterator begin, Iterator end) const
{
Iterator i = begin;

const size_t buffer_len = std::distance(begin,end); <-- this is not work usualy distance here is 1

if(buffer_len >= len_)
{
std::advance(i, len_);
return std::make_pair(i, true);
}

while (i != end)
if (c_ == *i++) {
return std::make_pair(i, true);
}
return std::make_pair(i, false);
}

private:
char c_;
int len_;
};

namespace boost {
namespace asio {
template <> struct is_match_condition<match_char>
: public boost::true_type {};
}
}


boost::asio::streambuf b;

void main() {

boost::asio::async_read_until(port, b,
match_char(';', 128) , &handler);

}

最佳答案

自定义 MatchCondition 条件不允许限制从流中读取的字节数不超过 n 字节数。 read_until() 系列函数都允许将超出分隔符的数据从 Stream 中读取到 streambuf 中。本质上,read_until() 将从 streambuf 中准备一个缓冲区,从 Stream 中读取一 block 数据到准备好的缓冲区中,然后使用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_found buffer.size() 将为 128
  • 如果找到分隔符,则 error 将成功,bytes_transferred 将是驻留在 缓冲区中的字节数,包括分隔符在内 的输入序列。请注意,buffer.size() 可能大于 bytes_transferred,但不会超过 128
  • 如果未读取 128 字节且未找到定界符,则 error 将包含有关读取操作失败原因的适当错误条件,例如 boost::asio::error::eof 如果远程端关闭了连接。

这是一个完整的例子demonstrating streambuf 的行为:

#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

关于c++ - boost async_read_until 将 match_condition 与限制大小结合起来读取,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32273929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com