有没有办法在找到匹配的字符或收到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);
答案 0 :(得分:2)
自定义MatchCondition
条件不允许限制从流中读取的字节数不超过n
个字节数。 read_until()
函数族都允许从Stream
和streambuf
读取分隔符以外的数据。本质上,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_found
,buffer.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