我正在使用boost::asio::read_until
从套接字读取,直到"
收到.但是,有人可能会发送数十亿和数十亿字节,直到系统耗尽RAM并且必须关闭.
为了避免这种情况,我想设置一个限制read_until
.比如"直到"
或达到10MB 才读".
是否有一个简单的解决方案read_until
,或者我必须切换到接收read
时手动结束读数"
?
@sehe有一个很好的答案,允许停止EOF或读取特定数量的字节.我的版本稍微复杂得多,但另外允许在任何分隔符上停止.
您可以使用max size参数构造 boost :: asio :: streambuf:
basic_streambuf的构造函数接受size_t参数,该参数指定输入序列和输出序列的大小总和的最大值.在basic_streambuf对象的生命周期中,以下不变量成立:
size() <= max_size()
如果成功导致违反不变量的任何成员函数将抛出类std :: length_error的异常.
或者您可以使用此重载:
template< typename SyncReadStream, typename Allocator, typename MatchCondition> std::size_t read_until( SyncReadStream & s, boost::asio::basic_streambuf< Allocator > & b, MatchCondition match_condition, boost::system::error_code & ec, typename enable_if< is_match_condition< MatchCondition >::value >::type * = 0);
匹配条件函数看起来像这样:
using iterator = buffers_iterator::const_buffers_type>; /** \brief Make read_until stop when either: * the stop character was found * more than 100MB have been read */ pair match_condition(iterator begin, iterator end) { // to much data? if(end - begin > 100*1024*1024) { return std::make_pair(begin, true); } // try and find stop character for(auto i = begin; i < end; i++) { auto c = i.rdbuf()->sgetc(); if(c == STOP_CHARACTER) { return std::make_pair(i, true); } } return std::make_pair(begin, false); }
(使用多字符分隔符进行此工作留给读者练习)
只需使用transfer_exactly
其中将还停留在EOF或缓冲区已满:
auto transferred = read(s, sb, transfer_exactly(10u<<20), ec);
Live On Coliru
#include#include using namespace boost::asio; using namespace ip; int main() { boost::system::error_code ec; io_service svc; tcp::socket s(svc); s.connect(tcp::endpoint(address_v4::loopback(), 6767)); streambuf sb; auto transferred = read(s, sb, transfer_exactly(10u<<20), ec); std::cerr << "read " << transferred << " till " << ec.message() << "\n"; }