基于行的操作

许多广泛应用的网络协议是基于行的,这意味着许多协议元素通过" "来分割,比如HTTP、SMPT、FTP,为了更方便的实现基于行的协议,和其他基于分隔符的协议一样,Boost::Asio包括了read_until() 和async_read_until()。
下面的例子阐述了async_read_until() 在HTTP server的应用,为了从HTTP client接收第一行
class http_connection
{
  ...
  void start()
  {
    boost::asio::async_read_until(socket_, data_, " ",
        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的数据成员保存了从socket接收到的没有被分割的数据,在分隔符后面还可能有很多数据,多余的数据应当留在streambuf 中,并使用read_until() 或者 async_read_until()来检查子序列
分隔符可能是一个单独的char,一个std::string或者boost::regex,read_until() 和 async_read_until() 也包含了用户自定义函数对象作为匹配条件的重载,比如,一直读数据直到遇到一个空白字符
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);
从流缓存中读数据,知道遇到一个匹配的字符
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 {};
} } // namespace boost::asio
...
boost::asio::streambuf b;
boost::asio::read_until(s, b, match_char('a'));
is_match_condition<> 自动评估函数的结果是true还是false,以及拥有前台的result_type 定义的函数对象。其他类型必须显式指定,就像上面写的那样
原文地址:https://www.cnblogs.com/learn-my-life/p/5272220.html