Многие широко используемые интернет-протоколы основаны на линиях, что означает, что они имеют элементы протокола, которые ограничены последовательностью символов<"\r\n"
>. Примеры включают HTTP, SMTP и FTP. Для более легкой реализации линейных протоколов, а также других протоколов, использующих разграничители, Boost. Азио включает в себя функции<read_until()
>и<async_read_until()
>.
Следующий пример иллюстрирует использование<async_read_until()
>в HTTP-сервере для получения первой строки HTTP-запроса от клиента:
class http_connection
{
...
void start()
{
boost::asio::async_read_until(socket_, data_, "\r\n",
boost::bind(&http_connection::handle_request_line, this, _1));
}
void handle_request_line(boost::system::error_code ec)
{
if (!ec)
{
std::string method, uri, version;
char sp1, sp2, cr, lf;
std::istream is(&data_);
is.unsetf(std::ios_base::skipws);
is >> method >> sp1 >> uri >> sp2 >> version >> cr >> lf;
...
}
}
...
boost::asio::ip::tcp::socket socket_;
boost::asio::streambuf data_;
};
<streambuf
>элемент данных служит местом для хранения данных, которые были прочитаны из гнезда, прежде чем он будет найден для разграничителя. Важно помнить, что могут быть дополнительные данные.послеразграничителя. Эти избыточные данные следует оставить в<streambuf
>, чтобы они могли быть проверены последующим вызовом<read_until()
>или<async_read_until()
>.
Ограничители могут быть определены как один<char
>,<std::string
>или<boost::regex
>. Функции<read_until()
>и<async_read_until()
>также включают перегрузки, которые принимают определяемый пользователем объект функции, называемый условием соответствия. Например, для считывания данных в streambuf, пока не встретится белое пространство:
typedef boost::asio::buffers_iterator<
boost::asio::streambuf::const_buffers_type> iterator;
std::pair<iterator, bool>
match_whitespace(iterator begin, iterator end)
{
iterator i = begin;
while (i != end)
if (std::isspace(*i++))
return std::make_pair(i, true);
return std::make_pair(i, false);
}
...
boost::asio::streambuf b;
boost::asio::read_until(s, b, match_whitespace);
Для чтения данных в streambuf до тех пор, пока не будет найден соответствующий символ:
class match_char
{
public:
explicit match_char(char c) : c_(c) {}
template <typename Iterator>
std::pair<Iterator, bool> operator()(
Iterator begin, Iterator end) const
{
Iterator i = begin;
while (i != end)
if (c_ == *i++)
return std::make_pair(i, true);
return std::make_pair(i, false);
}
private:
char c_;
};
namespace boost { namespace asio {
template <> struct is_match_condition<match_char>
: public boost::true_type {};
} }
...
boost::asio::streambuf b;
boost::asio::read_until(s, b, match_char('a'));
Характер<is_match_condition<>
>типа автоматически оценивает истинность для функций и для функциональных объектов с вложенным<result_type
>типдефом. Для других типов черта должна быть явно специализирована, как показано выше.
async_read_until(),is_match_condition,read_until(),streambuf,HTTP Client example.